使用 base64 编码内容从 XML 创建 ZipArchive

Create ZipArchive from XML with base64 encoded content

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

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

我无法打开 FINAL ZIP 文件。 我得到:"Windows cannot open the folder. The Compressed(zipped) Folder'c:\path\file.zip' is invalid."

我可以将原始 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();

没有 a good, minimal, complete code example,就不可能确定代码中有哪些错误。但是您 post 编辑的代码片段中至少有两个明显的错误,其中之一很容易导致 "invalid .zip" 错误:

  1. 在语句 writer.Write(xDocReport.ToString()); 中,变量 xDocReport 没有被初始化为任何有用的东西,至少在您 post 编辑的代码中没有。所以你会在存档中得到一个空的 XML 文档。

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

不过问题更多……

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

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

如果以上内容无法解决您的问题,您应该编辑 post,以提供更好的代码示例。


最后一条评论:当您要用另一个对象替换该对象时,将 xDoc 之类的变量初始化为空 XDocument 对象是没有意义的(例如,通过调用 XDocument.Load() ).