如何避免在.NET的ZipPackage类中出现[Content_Types].xml

19

我想知道在使用.net的ZipPackage类时,有没有办法避免在zip文件中包含[Content_Types].xml文件。


你使用 ZipPackage 的原因是什么?如果你想将现有文档创建为 zip 文件,最好使用 System.IO.Compression 命名空间中的 GZipStream 和相关类。 - shahkalpesh
6
GZipStream仅适用于单个文件。 - H H
@Henk:我想为单个文档创建一个“.zip”文件。使用GZipStream可以创建“.zip”文件吗? - Kushal Waikar
@Kushal:不,如果你想要用其他Zip工具读取它的话就不行。 - H H
1
.NET 4.5 添加了 ZipArchive 类来实现这一功能(http://msdn.microsoft.com/zh-cn/library/system.io.compression.ziparchive%28v=vs.110%29.aspx)。 - Govert
6个回答

9

编号。

Zip包不是普通的Zip文件。它们必须遵循一种强制性结构,并在根目录中包含Content_Types.xml文件。ZipPackage = ZipArchive + Structure

如果您想创建(特别是如果您想读取)普通的Zip归档文件,则需要使用额外的库,BCL中没有支持。

请参见SharpZipLib(GPL)和DotNetZip


“正常”是什么意思?使用 .net 框架内的任何内容都无法创建“.zip”文件吗? - Kushal Waikar
1
@Kushal:Package(包)= Zip(压缩)归档 + 结构。因此,您可以使用WinZip读取Zip包,但不能使用ZipPackage读取(所有)Zip文件。 - H H
我只想压缩一个单独的文件。但是我无法摆脱嵌入到包中的 .xml 文件。 - Kushal Waikar
2
contents.xml 是使它成为一个包的内容。 - H H

5
如果你没有调用.Flush()方法,那么该文件将不存在。

1
这是对这个问题的一个很好的答案,这种技术对我很有效。如果你使用内存流创建你的ZipPackage,添加你的部分,然后在处理ZipPackage之前复制流(调用.Flush()),那么生成的zip文件仅包含你添加的部分,而没有"[Context_Types].xml"。 - Matt Klein
@DLeh 对不起,你是什么意思?这正是避免文件被添加到压缩文件中的方法。 - Yiping
@MattKlein 谢谢。我是偶然发现的(我忘记释放了)。但它似乎在工作。 - Yiping
清空谁?Package,MemoryStream等? - Murilo
@MattKlein 如果我需要添加多个文件怎么办?我必须在打开下一个文件之前刷新它。 - Imad

2
是的,您可以创建不带额外XML内容文件的zip包 受此链接的启发:使用System.IO.Packaging生成ZIP文件 使用上述由Yiping提到的发现,您可以避免将额外的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.
        }
    }
}

搞定了,谢谢。重要的部分是memStream.Position = 0; 没有它你会得到一个空的zip文件。 - apc
3
CopyStream是从哪里来的?我测试了你的代码,但当我尝试提取.zip文件的内容时,显示文件已损坏。 - Mauricio Arias Olave
它能够工作,但是如果存在大量文件,将在Web环境中抛出OutOfMemoryException异常。 - Murilo

1
男士,这对我帮助很大!你太棒了!我必须使用它,因为我的旧框架(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);
    }

0

您还可以使用DynamicObjectSystem.IO.Packaging.Package的私有字段_contentTypeHelper设置为null


0

当你完成打包压缩文件时,请运行此函数:

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{}
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接