web-dev-qa-db-ja.com

ZipArchiveが予期しないデータ破損エラーのエラーを表示する

私はいくつかのバイト配列データを使用してその場でZipストリームを作成し、MVCアクションを介してダウンロードできるようにしています。

ただし、ダウンロードしたファイルをWindowsで開くと、常に次の破損したエラーが発生します。

enter image description here

そして、私が7zからxtractしようとすると、このエラー

enter image description here

ただし、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");
    }

ここで何が悪いのでしょうか。

私は一日中これに苦労しているので、どんな助けも高く評価されます。

前もって感謝します

18
Faraj Farook

zipArchiveの外でzipStream.ToArray()を使用して移動します。

問題の理由は、ストリームがバッファリングされていることです。それを扱うにはいくつかの方法があります:

  • ストリームのAutoFlushプロパティをtrueに設定できます。
  • ストリームで手動で.Flush()を呼び出すことができます。

または、MemoryStreamであり、.ToArray()を使用しているため、ストリームを最初に閉じる/破棄することを許可できます(これは、using)。

27
John

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();
}
2
Afshin Razaghi

これにも問題があり、問題はアーカイブ自体の生成ではなく、AngularJSでのGETリクエストの処理方法にあることがわかりました。

この投稿は私を助けました: angularを使用してZipファイルをダウンロードする方法

キーはresponseType: 'arraybuffer'私の$ http呼び出しに。

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