如何避免.net';s ZipPackage类

如何避免.net';s ZipPackage类,.net,.net-4.0,zip,.net,.net 4.0,Zip,我想知道在使用.net的ZipPackage类时,是否有任何方法可以避免在zip文件中包含[Content\u Types].xml文件。否 Zip包不是(普通)Zip文件。它们必须遵循强制结构,并在根目录中包含Content\u Types.xml文件ZipPackage=ZipArchive+结构 如果您想创建(尤其是如果您想阅读)普通的Zip归档文件,您将需要一个额外的库,BCL中没有支持 请参阅(GPL)和如果不调用.Flush()方法,则不会有此类文件是的,您可以创建zip包,而不添加

我想知道在使用.net的ZipPackage类时,是否有任何方法可以避免在zip文件中包含[Content\u Types].xml文件。

Zip包不是(普通)Zip文件。它们必须遵循强制结构,并在根目录中包含
Content\u Types.xml
文件<代码>ZipPackage=ZipArchive+结构

如果您想创建(尤其是如果您想阅读)普通的Zip归档文件,您将需要一个额外的库,BCL中没有支持


请参阅(GPL)和

如果不调用.Flush()方法,则不会有此类文件

是的,您可以创建zip包,而不添加额外的XML内容文件

受此链接启发:

使用上面提到的发现可以避免向包中添加额外的xml文件。在关闭zip存档之前,将zip流从内存流保存到物理zip文件,如下所示:

public static void AddFilesToZip(string zipFilename, List<String> filesToAdd)
{
    using (var memStream = new MemoryStream())
    {
        using (Package zip = System.IO.Packaging.Package.Open(memStream, FileMode.Create))
        {

            foreach (var fileToAdd in filesToAdd)
            {
                string destFilename = ".\\" + Path.GetFileName(fileToAdd);
                Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));

                //Existing parts not likely in fresh memory stream
                if (zip.PartExists(uri))
                {
                    zip.DeletePart(uri);
                }

                PackagePart part = zip.CreatePart(uri, "", CompressionOption.Normal);

                using (FileStream fileStream = new FileStream(fileToAdd, FileMode.Open, FileAccess.Read))
                {

                    using (Stream dest = part.GetStream())
                    {
                        CopyStream(fileStream, dest);
                    }
                }
            }

            //The zip Package will add an XML content type file to memeory stream when it closes
            //so before it closes we save the memorystream to physical zip file.
            using (FileStream zipfilestream = new FileStream(zipFilename, FileMode.Create, FileAccess.Write))
            {
                memStream.Position = 0;
                CopyStream(memStream, zipfilestream);
            }

            // That's it. Zip file saved to file. Things added by package after this point will be to memory stream finally disposed.
        }
    }
}
publicstaticvoid AddFilesToZip(字符串zipFilename,列表filesToAdd)
{
使用(var memStream=new MemoryStream())
{
使用(Package zip=System.IO.Packaging.Package.Open(memStream,FileMode.Create))
{
foreach(filesToAdd中的var fileToAdd)
{
字符串destFilename=“.\\”+Path.GetFileName(fileToAdd);
uriuri=PackUriHelper.CreatePartUri(新Uri(destFilename,UriKind.Relative));
//新内存流中可能不存在的现有部分
if(zip.PartExists(uri))
{
DeletePart(uri);
}
PackagePart=zip.CreatePart(uri,“,CompressionOption.Normal);
使用(FileStream FileStream=newfilestream(fileToAdd,FileMode.Open,FileAccess.Read))
{
使用(Stream dest=part.GetStream())
{
CopyStream(文件流、目的地);
}
}
}
//zip包在关闭时将向memeory流添加一个XML内容类型文件
//因此,在它关闭之前,我们将memorystream保存到物理zip文件中。
使用(FileStream zipfilestream=newfilestream(zipFilename,FileMode.Create,FileAccess.Write))
{
memStream.Position=0;
CopyStream(memStream、zipfilestream);
}
//这就是保存到文件中的.Zip文件。在这一点之后由包添加的东西将最终被释放到内存流中。
}
}
}

伙计,这对我帮助很大!你太棒了!我不得不使用它,因为我的旧框架(3.5)。仅作为补充,请参见以下CopyStream功能的实现:

    private void CopyStream(Stream source, Stream target)
    {
        const int bufSize = 0x1000;
        byte[] buf = new byte[bufSize];
        int bytesRead = 0;
        while ((bytesRead = source.Read(buf, 0, bufSize)) > 0)
            target.Write(buf, 0, bytesRead);
    }

您还可以将
System.IO.Packaging.Package
的私有字段
\u contentTypeHelper
设置为
null
(使用
DynamicObject
)。

打包完zip文件后运行此功能:

public static void Remove_Content_Types_FromZip(string zipFileName)
    {
        string contents;
        using (ZipFile zipFile = new ZipFile(File.Open(zipFileName, FileMode.Open)))
        {
            /*
            ZipEntry startPartEntry = zipFile.GetEntry("[Content_Types].xml");
            using (StreamReader reader = new StreamReader(zipFile.GetInputStream(startPartEntry)))
            {
                contents = reader.ReadToEnd();
            }
            XElement contentTypes = XElement.Parse(contents);
            XNamespace xs = contentTypes.GetDefaultNamespace();
            XElement newDefExt = new XElement(xs + "Default", new XAttribute("Extension", "sab"), new XAttribute("ContentType", @"application/binary; modeler=Acis; version=18.0.2application/binary; modeler=Acis; version=18.0.2"));
            contentTypes.Add(newDefExt);
            contentTypes.Save("[Content_Types].xml");
            zipFile.BeginUpdate();
            zipFile.Add("[Content_Types].xml");
            zipFile.CommitUpdate();
            File.Delete("[Content_Types].xml");
            */
            zipFile.BeginUpdate();
            try
            {
                zipFile.Delete("[Content_Types].xml");
                zipFile.CommitUpdate();
            }
            catch{}
        }
    }

您使用
ZipPackage
的原因是什么?如果您希望用现有文档创建zip文件,最好使用
System.IO.Compression
命名空间中的
GZipStream
相关类。@shahkalpesh:GZipStream仅用于单个文件。@Henk:我希望为单个文档创建一个.zip文件。是否可以使用GZipStream创建“.zip”文件?@Kushal:不,如果您想使用其他zip工具读取它,则不可以。.NET 4.5添加了一个ZipArchive类来执行此操作()“正常”是什么意思?无法使用.net framework中的任何内容创建“.zip”文件吗?@Kushal:Package=zip Archive+Structure。因此,您可以使用WinZip读取Zip包,但无法使用ZIPPACKAGE读取(所有)Zip文件。我只希望压缩单个文件。但是我无法摆脱嵌入包中的.xml文件。contents.xml是包的组成部分。这是对这个问题的一个极好的回答,这种技术对我很有效。如果使用内存流创建
ZipPackage
,添加部件,然后在处理
ZipPackage
(调用
.Flush()
)之前复制该流,则生成的zip文件仅包含添加的部件,而不包含“[Context\u Types].xml”。@DLeh抱歉,这是什么意思?这正是避免文件被添加到zip文件的方法。@MattKlein谢谢。我偶然发现了这个(我忘了处理)。但它似乎起作用了。冲谁?Package、MemoryStream等?@MattKlein如果我需要添加多个文件怎么办?在打开下一个文件之前,我必须刷新它。这个可以用了,谢谢。重要的部分是memStream.Position=0;如果没有这个,你将得到一个空的zip。
CopyStream
从哪里来?我测试了你的代码,但是当我提取.zip的内容时,它说.zip已损坏。它可以工作,但如果有很多文件,它会在web环境中抛出OfMemoryException。