C# 使用Zip库创建Epub文件

C# 使用Zip库创建Epub文件,c#,zip,epub,C#,Zip,Epub,大家好 我正在尝试压缩我用c制作的一个Epub文件# 我尝试过的事情 点网拉链http://dotnetzip.codeplex.com/ -DotNetZip可以工作,但epubcheck无法生成文件(**请参见下面的编辑) ZipStorer ZipStorer.codeplex.com -创建通过验证但无法在Adobe Digital Edition中打开的epub文件 7拉链 -我没有使用c#尝试过这个方法,但是当我使用there接口压缩文件时,它告诉我mimetype文件名的长度是9

大家好

我正在尝试压缩我用c制作的一个Epub文件#

我尝试过的事情

  • 点网拉链http://dotnetzip.codeplex.com/
  • -DotNetZip可以工作,但epubcheck无法生成文件(**请参见下面的编辑)
  • ZipStorer ZipStorer.codeplex.com
  • -创建通过验证但无法在Adobe Digital Edition中打开的epub文件
  • 7拉链
  • -我没有使用c#尝试过这个方法,但是当我使用there接口压缩文件时,它告诉我mimetype文件名的长度是9,应该是8
在所有情况下,mimetype文件都是添加到归档文件中的第一个文件,不会被压缩

我正在使用的Epub验证器是epubcheck

如果有人使用这些库之一成功地压缩了一个epub文件,请让我知道如何或是否有人使用任何其他开源压缩api成功地压缩了一个epub文件,这些api也可以工作


编辑


DotNetZip可以工作,请参阅下面接受的答案。

如果需要控制ZIP文件中条目的顺序,可以使用DotNetZip和ZipOutputStream

您说您尝试了DotNetZip,但它(epub验证器)给了您一个错误,抱怨mime类型的问题。这可能是因为您在DotNetZip中使用了ZipFile类型。如果您使用ZipoutStream,您可以控制zip条目的顺序,这显然对epub很重要(我不知道格式,只是猜测)


编辑

我刚刚检查了一下,然后描述了如何格式化.epub文件。它说mimetype文件必须包含特定的文本,必须是未压缩和未加密的,并且必须显示为ZIP存档中的第一个文件

使用ZipOutputStream,可以通过在特定的ZipEntry上设置CompressionLevel=None来实现这一点-该值不是默认值

下面是一些示例代码:

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);
        }
    }
}

请参阅ZipOutputStream的文档

为什么不让生活更轻松

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();
    }
}

对于像我这样正在寻找其他方法的人,我想补充一点,Jaime Olivares的ZipStorer类是一个很好的选择。您可以将代码直接复制到项目中,并且很容易在“deflate”和“store”之间进行选择

以下是我创建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, "");
    }
}
Dictionary FilesToZip=newdictionary()
{
{ConfigPath+@“mimetype”,@“mimetype”},
{ConfigPath+@“container.xml”,@“META-INF/container.xml”},
{OutputFolder+Name.Output\u OPF\u Name,@“OEBPS/”+Name.Output\u OPF\u Name},
{OutputFolder+Name.Output\u XHTML\u Name,@“OEBPS/”+Name.Output\u XHTML\u Name},
{ConfigPath+@“style.css”、@“OEBPS/style.css”},
{OutputFolder+Name.Output\u NCX\u Name,@“OEBPS/”+Name.Output\u NCX\u Name}
};
使用(ZipStorer EPUB=ZipStorer.Create(OutputFolder+“book.EPUB”,“”)
{
bool First=true;
foreach(FilesToZip中的KeyValuePair文件)
{
if(First){EPUB.AddFile(ZipStorer.Compression.Store,File.Key,File.Value,”);First=false;}
else EPUB.AddFile(ZipStorer.Compression.Deflate,File.Key,File.Value,“”);
}
}

这段代码创建了一个完全有效的EPUB文件。然而,如果您不需要担心验证,那么大多数电子阅读器似乎都会接受带有“deflate”mimetype的EPUB。因此,我以前使用.NET的ZipArchive编写的代码生成了在Adobe Digital Edition和PocketBook中工作的ePub。

您是说这些实用程序无法压缩您的文件,还是说在使用gzip(或其他功能)时无法压缩文件c#返回错误或您的epub文件有问题?epub文件没有错误,但当我对其运行验证程序时,我得到一个关于mimetype文件的错误,如果您编写文件并使用WinZip怎么办?它验证了吗?非常感谢您的快速、解释得很好的回答,我只需要更改两件事:output.putnextery(“META-INF/”);不需要,只是在zip文件夹中创建一个空的META-INF文件,在WriteExistingFile中,我更改了outputFileName为filename,我想这可能会帮助其他人查看您的答案。再次感谢Hey claybo,谢谢。我修改了示例代码来解决这两个问题。我不确定epub文件中是否需要OPS/(内容目录)和META-INF/(元数据目录)。谢谢。这帮助我编写了一个ePub生成器,因为7zip让我失望。7zip似乎无法正确使用mimetype。我还让它通过为每种电子书类型传递一个要压缩的文件列表来进行多个构建(B&N、Kindle、iBooks、Short Sample)。