问题
I've written some code generating ePub archive using .NET 4.5 System.IO.Compression.ZipArchive. I need this to be part of a Portable Class Library (PCL), hence using a subset of .NET fx.
I have issue with the mimetype file containing the magic 'application/epub+zip'. Having read the specs, I add that file first with no compression.
Despite this care, the produced ePub archive isn't conforming to specs. Specs demand the content of the mimetype file should start at position 38. Mine starts at position 47.
There isn't any parameter on ZipArchive itself and ZipArchiveEntry can only be parametrized by compression mode only. I'm a bit confused since I thought Zip files came in one variety and I don't understand what influences this specific behaviour.
For reference, here are the first bits of a sample ePub (working that is):
and here is mine:
回答1:
You did not set compression method to 'no compression'. Bytes 9-10 of the data are for compression method, for working file it is 00, as it should be, but in your case they are set to 8 - 'deflate'. Compression level is not compression method, and setting it to 0 still uses deflate. You should try another library, like SecureBlackbox, or DotNetZip.
回答2:
As Nickolay points out, the 'deflate' method is being used instead of 'store'. It was a real pain for me to find out how to fix this, and for anyone else who finds this topic, I used the ZipStorer class by Jaime Olivares to add the mimetype using 'store'.
https://github.com/jaime-olivares/zipstorer
It's easy to add this code to a C# project (it's not a DLL), and it's easy to add files using 'store' instead of 'deflate'. Here's my code for doing that:
Dictionary<string, string> FilesToZip = new Dictionary<string, string>()
{
{ ConfigPath + @"mimetype", @"mimetype"},
{ ConfigPath + @"container.xml", @"META-INF/container.xml" },
{ OutputFolder + Name.Output_OPF_Name, @"OEBPS/" + Name.Output_OPF_Name},
{ OutputFolder + Name.Output_XHTML_Name, @"OEBPS/" + Name.Output_XHTML_Name},
{ ConfigPath + @"style.css", @"OEBPS/style.css"},
{ OutputFolder + Name.Output_NCX_Name, @"OEBPS/" + Name.Output_NCX_Name}
};
using (ZipStorer EPUB = ZipStorer.Create(OutputFolder + "book.epub", ""))
{
bool First = true;
foreach (KeyValuePair<string, string> File in FilesToZip)
{
if (First) { EPUB.AddFile(ZipStorer.Compression.Store, File.Key, File.Value, ""); First = false; }
else EPUB.AddFile(ZipStorer.Compression.Deflate, File.Key, File.Value, "");
}
}
This code creates a perfectly valid EPUB file. However, if you don't need to worry about validation, it seems most eReaders will accept an EPUB with a 'deflate' mimetype. So my previous code using .NET's ZipArchive produced EPUBs that worked in Adobe Digital Editions and a PocketBook. For example:
/*using (ZipArchive EPUB = ZipFile.Open(OutputFolder + Name.Output_EPUB_Name, ZipArchiveMode.Create))
{
foreach (KeyValuePair<string, string> AddFile in AddFiles)
{
if (AddFile.Key.Contains("mimetype"))
{
EPUB.CreateEntryFromFile(AddFile.Key, AddFile.Value, CompressionLevel.NoCompression);
}
else EPUB.CreateEntryFromFile(AddFile.Key, AddFile.Value, CompressionLevel.Optimal);
}
}*/
回答3:
I did follow Nickolay's advice, I used DotNetZip to create an archive with only the mimetype file in it and use that file as a starting point for other epubs.
This approach allows me to use ZipArchive and its async interface while respecting ePub's specs.
来源:https://stackoverflow.com/questions/19645392/how-to-create-epub-with-system-io-compression-ziparchive