2016-10-21 28 views
6

1つ以上のファイルを含むzipファイルを作成しようとしています。
私は.NET Framework 4.5、より具体的にはSystem.IO.Compression名前空間を使用しています。
目的は、ユーザーがASP.NET MVCアプリケーションを通じてzipファイルをダウンロードできるようにすることです。
zipファイルが生成されてクライアントに送信されていますが、ダブルクリックすると次のエラーが表示されます。
Windowsではフォルダを開くことができません。 圧縮(zip)されたフォルダ...が無効です。System.IO.Compressionで作成したZipファイルが無効です

[HttpGet] 
public FileResult Download() 
{ 
    var fileOne = CreateFile(VegieType.POTATO); 
    var fileTwo = CreateFile(VegieType.ONION); 
    var fileThree = CreateFile(VegieType.CARROT); 

    IEnumerable<FileContentResult> files = new List<FileContentResult>() { fileOne, fileTwo, fileThree }; 
    var zip = CreateZip(files); 

    return zip; 
} 

private FileContentResult CreateFile(VegieType vType) 
{ 
    string fileName = string.Empty; 
    string fileContent = string.Empty; 

    switch (vType) 
    { 
     case VegieType.BATATA: 
      fileName = "batata.csv"; 
      fileContent = "THIS,IS,A,POTATO"; 
      break; 
     case VegieType.CEBOLA: 
      fileName = "cebola.csv"; 
      fileContent = "THIS,IS,AN,ONION"; 
      break; 
     case VegieType.CENOURA: 
      fileName = "cenoura.csv"; 
      fileContent = "THIS,IS,A,CARROT"; 
      break; 
     default: 
      break; 
    } 

    var fileBytes = Encoding.GetEncoding(1252).GetBytes(fileContent); 
    return File(fileBytes, MediaTypeNames.Application.Octet, fileName); 
} 

private FileResult CreateZip(IEnumerable<FileContentResult> files) 
{ 
    byte[] retVal = null; 

    if (files.Any()) 
    { 
     using (MemoryStream zipStream = new MemoryStream()) 
     { 
      using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, false)) 
      { 
       foreach (var f in files) 
       { 
        var entry = archive.CreateEntry(f.FileDownloadName, CompressionLevel.Fastest); 
        using (var entryStream = entry.Open()) 
        { 
         entryStream.Write(f.FileContents, 0, f.FileContents.Length); 
         entryStream.Close(); 
        } 
       } 

       zipStream.Position = 0; 
       retVal = zipStream.ToArray(); 
      } 
     } 
    } 

    return File(retVal, MediaTypeNames.Application.Zip, "horta.zip"); 
} 

は、誰もが、私はそれをダブルクリックしたときに、私のzipファイルが無効であることを言って窓のある理由についていくつかの光を当てることができますしてください:
はここに私のコードです。
最後に、7-Zipを使用して開くことができます。

答えて

8

ZipArchiveオブジェクトが破棄された後、ToArray経由でMemoryStreamバッファを取得する必要があります。そうしないと、壊れたアーカイブになります。

また、ZipArchiveコンストラクタのパラメータを変更して、エントリを追加するときに開いたままにすることに注意してください。

ZipArchiveが処分されているときにチェックサムが発生しています。その前にMemoryStreamを読んでもまだ不完全です。

private FileResult CreateZip(IEnumerable<FileContentResult> files) 
    { 
     byte[] retVal = null; 

     if (files.Any()) 
     { 
      using (MemoryStream zipStream = new MemoryStream()) 
      { 
       using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) 
       { 
        foreach (var f in files) 
        { 
         var entry = archive.CreateEntry(f.FileDownloadName, CompressionLevel.Fastest); 
         using (BinaryWriter writer = new BinaryWriter(entry.Open())) 
         {         
          writer.Write(f.FileContents, 0, f.FileContents.Length); 
          writer.Close(); 
         } 
        } 

        zipStream.Position = 0; 
       } 
       retVal = zipStream.ToArray(); 
      } 
     } 

     return File(retVal, MediaTypeNames.Application.Zip, "horta.zip"); 
    } 
+0

OPは、彼が7-Zipを使用してそれを開くことができると言いました。だからDisposeは発行しないでください – GauravKP

+0

私はメソッドの彼の両方のバージョンをテストし、私の方法で、ウィンドウzipで開くに失敗した、あなたはWindows zipで開くことができます、あなたはそれをテストしましたか? –

+0

ZipArchiveを処分する前にメモリストリームの位置を0に設定することをお勧めします。 ZipArchiveのディスポーザル私は、ジップのファイナライズをいくつか行います。 – Dave

2

だけストリームを返す...

private ActionResult CreateZip(IEnumerable files) 
{ 
    if (files.Any()) 
    { 
     MemoryStream zipStream = new MemoryStream(); 
     using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, false)) 
     { 
      foreach (var f in files) 
      { 
       var entry = archive.CreateEntry(f.FileDownloadName, CompressionLevel.Fastest); 
       using (var entryStream = entry.Open()) 
       { 
        entryStream.Write(f.FileContents, 0, f.FileContents.Length); 
        entryStream.Close(); 
       } 
      } 

     } 

     zipStream.Position = 0; 
     return File(zipStream, MediaTypeNames.Application.Zip, "horta.zip"); 
    } 

    return new EmptyResult(); 
}
+0

yip、同じことは... zipArchiveが破棄された後にストリームからバイトコンテンツを取得する –

0

はこの使用法では

using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) 

using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, false)) 

を変更してみてください、アーカイブはに書き込むことを余儀なくされますストリームが閉じているときただし、コンストラクタのleaveOpen引数がfalseに設定されている場合は、基になるストリームも閉じます。

関連する問題