开发者

Creating an Epub file with a Zip library

HI All,

I am trying to zip up an Epub file i have made using c#

Things I have tried

  • Dot Net Zip http://dotnetzip.codeplex.com/
  • - DotNetZip works but epubcheck fails the resulting file (**see edit below)
  • ZipStorer zipstorer.codeplex.com
  • - creates an epub file that p开发者_如何学编程asses validation but the file won't open in Adobe Digital Editions
  • 7 zip
  • - I have not tried this using c# but when i zip the file using there interface it tells me that the mimetype file name has a length of 9 and it should be 8

In all cases the mimetype file is the first file added to the archive and is not compressed

The Epub validator that I'am using is epubcheck http://code.google.com/p/epubcheck/

if anyone has succesfully zipped an epub file with one of these libraries please let me know how or if anyone has zipped an epub file successfully with any other open source zipping api that would also work.


EDIT

DotNetZip works, see accepted answer below.


If you need to control the order of the entries in the ZIP file, you can use DotNetZip and the ZipOutputStream.

You said you tried DotNetZip and it (the epub validator) gave you an error complaining about the mime type thing. This is probably because you used the ZipFile type within DotNetZip. If you use ZipOutputStream, you can control the ordering of the zip entries, which is apparently important for epub (I don't know the format, just surmising).


EDIT

I just checked, and the epub page on Wikipedia describes how you need to format the .epub file. It says that the mimetype file must contain specific text, must be uncompressed and unencrypted, and must appear as the first file in the ZIP archive.

Using ZipOutputStream, you would do this by setting CompressionLevel = None on that particular ZipEntry - that value is not the default.

Here's some sample code:

private void Zipup()
{
    string _outputFileName = "Fargle.epub";
    using (FileStream fs = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite ))
    {
        using (var output= new ZipOutputStream(fs))
        {
            var e = output.PutNextEntry("mimetype");
            e.CompressionLevel = CompressionLevel.None;

            byte[] buffer= System.Text.Encoding.ASCII.GetBytes("application/epub+zip");
            output.Write(buffer,0,buffer.Length);

            output.PutNextEntry("META-INF/container.xml");
            WriteExistingFile(output, "META-INF/container.xml");
            output.PutNextEntry("OPS/");  // another directory
            output.PutNextEntry("OPS/whatever.xhtml");
            WriteExistingFile(output, "OPS/whatever.xhtml");
            // ...
        }
    }
}

private void WriteExistingFile(Stream output, string filename)
{
    using (FileStream fs = File.Open(fileName, FileMode.Read))
    {
        int n = -1;
        byte[] buffer = new byte[2048];
        while ((n = fs.Read(buffer,0,buffer.Length)) > 0)
        {
            output.Write(buffer,0,n);
        }
    }
}

See the documentation for ZipOutputStream here.


Why not make life easier?

private void IonicZip()
{
    string sourcePath = "C:\\pulications\\";
    string fileName = "filename.epub";

    // Creating ZIP file and writing mimetype
    using (ZipOutputStream zs = new ZipOutputStream(sourcePath + fileName))
    {
        var o = zs.PutNextEntry("mimetype");
        o.CompressionLevel = CompressionLevel.None;

        byte[] mimetype = System.Text.Encoding.ASCII.GetBytes("application/epub+zip");
        zs.Write(mimetype, 0, mimetype.Length);
    }

    // Adding META-INF and OEPBS folders including files     
    using (ZipFile zip = new ZipFile(sourcePath + fileName))
    {
        zip.AddDirectory(sourcePath  + "META-INF", "META-INF");
        zip.AddDirectory(sourcePath  + "OEBPS", "OEBPS");
        zip.Save();
    }
}


For anyone like me who's searching for other ways to do this, I would like to add that the ZipStorer class from Jaime Olivares is a great alternative. You can copy the code right into your project, and it's very easy to choose between 'deflate' and 'store'.

https://github.com/jaime-olivares/zipstorer

Here's my code for creating an EPUB:

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜