【问题标题】:Create ZipArchive from XML with base64 encoded content使用 base64 编码内容从 XML 创建 ZipArchive
【发布时间】:2015-02-23 14:01:37
【问题描述】:

我正在动态创建一个 XML 文件。 其中一个节点包含一个编码为 BASE64 字符串的 ZIP 文件。

然后我创建另一个 ZIP 文件。 我添加了这个 XML 文件和其他一些 JPEG 文件。 我将文件输出到浏览器。

我无法打开 FINAL ZIP 文件。 我得到:“Windows 无法打开文件夹。压缩(压缩)文件夹'c:\path\file.zip' 无效。”

我能够将我的原始 XML 文件保存到文件系统中。 我可以打开那个 XML 文件,解码 ZIP 节点并保存到文件系统。 然后我就可以毫无问题地打开那个 Zip 文件了。

我可以创建最终的 ZIP 文件,省略我的 XML 文件,ZIP 文件打开没有问题。

我似乎只是在尝试压缩一个 XML 文件时遇到问题,该文件有一个节点,其 ZIP 内容编码为 BASE64 字符串。

有什么想法吗?代码片段如下。大量编辑。

XDocument xDoc = new XDocument();
XDocument xDocReport = new XDocument();
XElement xNodeReport;

using (FileStream fsData = new FileStream(strFullFilePath, FileMode.Open, FileAccess.Read)) {
    xDoc = XDocument.Load(fsData);

xNodeReport = xDoc.Element("Data").Element("Reports").Element("Report");

//SNIP
//create XDocument xDocReport 
//SNIO

  using (MemoryStream zipInMemoryReport = new MemoryStream()) {
    using (ZipArchive zipFile = new ZipArchive(zipInMemoryReport, ZipArchiveMode.Update)) {
    //Add REPORT to ZIP file
    ZipArchiveEntry entryReport = zipFile.CreateEntry("data.xml");
      using (StreamWriter writer = new StreamWriter(entryReport.Open())) {
        writer.Write(xDocReport.ToString());
      } //END USING report entry
    }
    xNodeReport.Value = System.Convert.ToBase64String(zipInMemoryReport.GetBuffer());

  //I am able to write this file to disk and manipulate it no problem.
  //File.WriteAllText("c:\\users\\snip\\desktop\\Report.xml",xDoc.ToString());

  }

  //create ZIP for response
  using (MemoryStream zipInMemory = new MemoryStream()) {
    using (ZipArchive zipFile = new ZipArchive(zipInMemory, ZipArchiveMode.Update)) {

    //Add REPORT to ZIP file
    ZipArchiveEntry entryReportWrapper = zipFile.CreateEntry("Report.xml");

    //THIS IS THE STEP THAT makes the Zip "invalid".  Although i can open and manipulate this source file no problem.
    //********
      using (StreamWriter writer = new StreamWriter(entryReportWrapper.Open())) {
        xDoc.Save(writer);
      } 

    //Add JPEG(s) to report
    //Create Charts
    if (chkDLSalesPrice.Checked) {chartDownloadSP.SaveImage(entryChartSP.Open(), ChartImageFormat.Jpeg);}
    if (chkDLSalesDOM.Checked) {chartDownloadDOM.SaveImage(entryChartDOM.Open(), ChartImageFormat.Jpeg);}
    if (chkDLSPLP.Checked) {chartDownloadSPLP.SaveImage(entryChartSPLP.Open(), ChartImageFormat.Jpeg);}
    if (chkDLSPLP.Checked) {chartDownloadLP.SaveImage(entryChartLP.Open(), ChartImageFormat.Jpeg);}

  } // END USING ziparchive

Response.Clear();
Response.AppendHeader("content-disposition", "attachment; filename=file.zip");
Response.ContentType = "application/zip";
Response.BinaryWrite(zipInMemory.GetBuffer());
Response.End();

【问题讨论】:

    标签: c# asp.net zip linq-to-xml


    【解决方案1】:

    没有a good, minimal, complete code example,就不可能确定代码中有哪些错误。但是您发布的代码 sn-p 中至少有两个明显的错误,其中一个很容易导致“invalid .zip”错误:

    1. 在声明writer.Write(xDocReport.ToString()); 中,变量xDocReport 没有被初始化为任何有用的东西,至少在您发布的代码中没有。因此,您将在存档中获得一个空的 XML 文档。

    由于代码示例不完整,您可能只是从问题的代码示例中省略了将该变量初始化为其他内容。在任何情况下,即使您不这样做也只会导致存档中出现空的 XML 文档,而不是无效的存档。

    虽然有更多问题......

    1. 您在MemoryStream 对象上调用GetBuffer(),而不是ToArray()。你想要后者。前者获取MemoryStream 对象的整个 后备缓冲区,包括有效流末尾之后的未初始化字节。由于有效的 .zip 文件在文件末尾包含 CRC 值,因此添加额外的数据会导致任何尝试将文件作为 .zip 存档读取的内容都错过正确的 CRC,而是读取未初始化的数据。

    将您对GetBuffer() 的调用替换为对ToArray() 的调用。

    如果上述方法不能解决您的问题,您应该编辑您的帖子,以提供更好的代码示例。


    最后一条评论:当您打算用不同的对象替换该对象时(例如通过调用XDocument.Load()),将像xDoc 这样的变量初始化为空的XDocument 对象是没有意义的。

    【讨论】:

    • 嗨,彼得。关于我的代码示例,您在所有方面都是完全正确的。很抱歉,感谢您仍然花时间查看代码示例。 #1 与我不完整的代码示例有关。所有变量都已正确分配,我只需要删除创建文档的代码页。我现在要测试你的第 2 点。谢谢!!!
    • ToArray() 是解决方案。非常感谢您在我未能提供完整的代码示例时花费时间。谢谢!!!!
    猜你喜欢
    • 2012-10-27
    • 1970-01-01
    • 2016-08-28
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    相关资源
    最近更新 更多