web-dev-qa-db-ja.com

ziparchiveの中央ディレクトリ破損エラー

私のc#コードでは、ユーザーがブラウザーにダウンロードするためのZipフォルダーを作成しようとしています。したがって、ここでの考え方は、ユーザーがダウンロードボタンをクリックすると、Zipフォルダーを取得するというものです。

テストの目的で、私は単一のファイルを使用してそれを圧縮していますが、それが機能するときは複数のファイルがあります。

これが私のコードです

var outPutDirectory = AppDomain.CurrentDomain.BaseDirectory;
string logoimage = Path.Combine(outPutDirectory, "images\\error.png"); // I get the file to be zipped

HttpContext.Current.Response.Clear();
HttpContext.Current.Response.BufferOutput = false;
HttpContext.Current.Response.ContentType = "application/Zip";
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=pauls_chapel_audio.Zip");


using (MemoryStream ms = new MemoryStream())
     {
          // create new Zip archive within prepared MemoryStream
          using (ZipArchive Zip = new ZipArchive(ms))
             {
                    Zip.CreateEntry(logoimage);
                    // add some files to Zip archive

                    ms.WriteTo(HttpContext.Current.Response.OutputStream);
             }
     }

これを試してみると、このエラーが発生します

中央ディレクトリが破損しています。

[System.IO.IOException] = {"ストリームの開始前に位置を移動しようとしました。"}

例外が発生します

using(ZipArchive Zip = new ZipArchive(ms))

何かご意見は?

9
mohsinali1317

モードを指定せずにZipArchiveを作成しています。つまり、最初にモードから読み取ろうとしていますが、読み取るものはありません。これは、コンストラクター呼び出しでZipArchiveMode.Createを指定することで解決できます。

もう1つの問題は、出力にMemoryStreamを書き込んでいることですbeforeZipArchive...を閉じます。これは、ZipArchiveコードに 'がないことを意味します。家事をする機会がありました。ネストされたusingステートメントの後に書き込み部分を移動する必要がありますが、ストリームを開いたままにするには、ZipArchiveの作成方法を変更する必要があることに注意してください。

using (MemoryStream ms = new MemoryStream())
{
    // Create new Zip archive within prepared MemoryStream
    using (ZipArchive Zip = new ZipArchive(ms, ZipArchiveMode.Create, true))
    {
        Zip.CreateEntry(logoimage);
        // ...
    }        
    ms.WriteTo(HttpContext.Current.Response.OutputStream);
 }
18
Jon Skeet