【问题标题】:ZipArchive gives Unexpected end of data corrupted errorZipArchive 给出数据损坏错误的意外结束
【发布时间】:2018-05-22 07:35:04
【问题描述】:

我正在尝试使用一些字节数组数据动态创建一个 zip 流,并通过我的 MVC 操作将其下载。

但是下载的文件在windows中打开时总是报以下损坏的错误。

当我尝试从 7z 提取时出现此错误

但请注意,从 7z 中提取的文件没有损坏。

我正在使用ZipArchive,下面是我的代码。

    private byte[] GetZippedPods(IEnumerable<POD> pods, long consignmentID)
    {
        using (var zipStream = new MemoryStream())
        {
            //Create an archive and store the stream in memory.                
            using (var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
            {
                int index = 1;
                foreach (var pod in pods)
                {                        
                    var zipEntry = zipArchive.CreateEntry($"POD{consignmentID}{index++}.png", CompressionLevel.NoCompression);                       
                    using (var originalFileStream = new MemoryStream(pod.ByteData))
                    {
                        using (var zipEntryStream = zipEntry.Open())
                        {
                            originalFileStream.CopyTo(zipEntryStream);
                        }
                    }
                }
                return zipStream.ToArray();
            }
        }
    }

    public ActionResult DownloadPOD(long consignmentID)
    {
        var pods = _consignmentService.GetPODs(consignmentID);
        var fileBytes = GetZippedPods(pods, consignmentID);
        return File(fileBytes, MediaTypeNames.Application.Octet, $"PODS{consignmentID}.zip");
    }

我在这里做错了什么。

任何帮助都将不胜感激,因为我为此苦苦挣扎了一整天。

提前致谢

【问题讨论】:

    标签: c# .net asp.net-mvc system.io.compression


    【解决方案1】:

    使用zipArchivezipStream.ToArray() 移出zipArchive

    问题的原因是流被缓冲了。有几种处理方法:

    • 您可以将流的AutoFlush 属性设置为true
    • 您可以在直播中手动调用.Flush()

    或者,因为它是MemoryStream,而您正在使用.ToArray(),您可以简单地允许首先关闭/处理流(我们通过将其移到using之外来完成)。

    【讨论】:

    • 您介意解释一下为什么缓冲是个问题吗?
    • @CalculusWhiz 想象ZipArchive 写入 4 KB 块。您向其写入 19 KB。它已经刷新了 16 个字节的数据,并正在等待额外的 1 个字节将最后一个块刷新到底层流。如果您在此刷新发生之前尝试访问底层流的全部内容,您将只能获得 16 KB 的数据,而不是完整的 19 个。您可以使用我上面建议的方法之一强制刷新。
    【解决方案2】:

    我处理 ZipArchive 并解决了错误

     public static byte[] GetZipFile(Dictionary<string, List<FileInformation>> allFileInformations)
        {
    
            MemoryStream compressedFileStream = new MemoryStream();
            //Create an archive and store the stream in memory.
            using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, true))
            {
                foreach (var fInformation in allFileInformations)
                {
                    var files = allFileInformations.Where(x => x.Key == fInformation.Key).SelectMany(x => x.Value).ToList();
                    for (var i = 0; i < files.Count; i++)
                    {
                        ZipArchiveEntry zipEntry = zipArchive.CreateEntry(fInformation.Key + "/" + files[i].FileName);
    
                        var caseAttachmentModel = Encoding.UTF8.GetBytes(files[i].Content);
    
                        //Get the stream of the attachment
                        using (var originalFileStream = new MemoryStream(caseAttachmentModel))
                        using (var zipEntryStream = zipEntry.Open())
                        {
                            //Copy the attachment stream to the zip entry stream
                            originalFileStream.CopyTo(zipEntryStream);
                        }
                    }
                }
                //i added this line 
                zipArchive.Dispose();
    
                return compressedFileStream.ToArray();
            }
        }
    
    public void SaveZipFile(){
            var zipFileArray = Global.GetZipFile(allFileInformations);
            var zipFile = new MemoryStream(zipFileArray);
            FileStream fs = new FileStream(path + "\\111.zip", 
            FileMode.Create,FileAccess.Write);
            zipFile.CopyTo(fs);
            zipFile.Flush();
            fs.Close();
            zipFile.Close();
    }
    

    【讨论】:

      【解决方案3】:

      我也遇到了这个问题,我发现我的问题不是存档本身的生成,而是我如何在 AngularJS 中处理我的 GET 请求。

      这篇文章帮助了我:how to download a zip file using angular

      关键是将responseType: 'arraybuffer' 添加到我的$http 调用中。

      factory.serverConfigExportZIP = function () {
          return $http({
              url: dataServiceBase + 'serverConfigExport',
              method: "GET",
              responseType: 'arraybuffer'
          })
      };
      

      【讨论】:

        【解决方案4】:

        您可以删除“使用”并使用 Dispose 和 Close 方法 这对我有用

        ...
        zip.Dispose();
        zipStream.Close();
        return zipStream.ToArray();
        

        【讨论】:

          【解决方案5】:

          我知道这是一个 C# 问题,但对于托管 C++,请在完成后删除 ZipArchive^ 以修复错误。

          ZipArchive^ zar = ZipFile::Open(starget, ZipArchiveMode::Create);
          ZipFileExtensions::CreateEntryFromFile(zar, sfile1, "file.txt");
          ZipFileExtensions::CreateEntryFromFile(zar, sfile2, "file2.txt");
          delete zar;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-05-17
            • 2019-02-05
            • 2013-09-10
            • 2017-10-22
            • 2011-04-20
            • 1970-01-01
            相关资源
            最近更新 更多