【问题标题】:how to avoid [Content_Types].xml in .net's ZipPackage class如何避免 .net 的 ZipPackage 类中的 [Content_Types].xml
【发布时间】:2011-04-14 12:29:15
【问题描述】:

我想知道在使用 .net 的 ZipPackage 类。

【问题讨论】:

  • 您使用ZipPackage的原因是什么?如果您希望从现有文档中创建一个 zip 文件,最好使用 GZipStreamSystem.IO.Compression 命名空间中的相关类。
  • @shahkalpesh:GZipStream 仅适用于单个文件。
  • @Henk:我希望为单个文档创建一个“.zip”文件。是否可以使用 GZipStream 创建“.zip”文件?
  • @Kushal:不,如果您想使用其他 Zip 工具阅读它,则不会。
  • .NET 4.5 添加了一个 ZipArchive 类来执行此操作 (msdn.microsoft.com/en-us/library/…)

标签: .net .net-4.0 zip


【解决方案1】:

打包完 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{}
        }
    }

【讨论】:

    【解决方案2】:

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

    受此链接启发:Using System.IO.Packaging to generate a ZIP file

    使用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;没有这个你会得到一个空的拉链。
    • CopyStream 来自哪里?我测试了你的代码,但是当我提取 .zip 的内容时,说 .zip 已损坏。
    • 它可以,但是如果有很多文件,它会在Web环境中抛出OutOfMemoryException。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      伙计,这对我帮助很大!你摇滚!我不得不使用它,因为我的旧框架(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);
          }
      

      【讨论】:

        【解决方案5】:

        如果不调用.Flush()方法,就不会有这个文件

        【讨论】:

        • 这是对这个问题的一个很好的答案,而且这种技术对我有用。如果您使用内存流创建ZipPackage,添加您的部分,然后在处理ZipPackage(调用.Flush())之前复制流,则生成的zip文件仅包含您添加的部分,没有“[Context_Types] .xml”。
        • @DLeh 对不起,你是什么意思?这正是避免将文件添加到 zip 文件中的方法。
        • @MattKlein 谢谢。我偶然发现了这个(我忘了处理)。但它似乎奏效了。
        • 冲洗谁?包、MemoryStream 等?
        • @MattKlein 如果我需要添加多个文件怎么办?在打开下一个文件之前,我必须刷新它。
        【解决方案6】:

        没有。

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

        如果您想创建(特别是如果您想阅读)普通的 Zip 档案,您将需要一个额外的库,BCL 不支持。

        参见SharpZipLib(GPL)和DotNetZip

        【讨论】:

        • “正常”是什么意思?是否无法使用 .net 框架中的任何内容创建“.zip”文件?
        • @Kushal:包 = Zip 存档 + 结构。因此,您可以使用 WinZip 读取 Zip 包,但无法使用 ZipPackage 读取(所有)Zip 文件
        • 我只想压缩一个文件。但我无法摆脱嵌入到包中的 .xml 文件。
        • contents.xml 使它成为一个包。
        猜你喜欢
        • 2010-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-14
        • 1970-01-01
        • 2012-09-21
        • 1970-01-01
        相关资源
        最近更新 更多