2017-09-21 46 views
2

大規模なXMLファイルアーカイブをホストするサーバーがあり、APIがzip内の要求されたファイルを取得しています。 11個以下のファイルを選択すると、ジップは正常に戻ってきます。私はより多くを取得する場合は、zipファイルを開こうとすると、私は次のエラーが表示されますファイルをzip形式でダウンロードすると、ASP.NET MVCで破損したzipが発生する

「Windowsは、フォルダを開くことができません圧縮(zip形式)フォルダは 無効です。」ここで

zipファイルを作成するために、データクラスとメソッドです:

//Archive file containing filename and content as memory stream 
public class ArchiveFile { 
    public string FileName; 
    public System.IO.MemoryStream FileContent; 
} 

//Method to retrieve archive files and zip them 
public static System.IO.MemoryStream GetFilesAsZip (string[] arrFileNames) { 
    MemoryStream zipStream = null; 
    using (zipStream = new MemoryStream()) { 
     // Retrieve files using above method 
     ArchiveFile[] retrievedFiles = GetFilesFromArchive(arrFileNames); 
     // Initialize new ZipArchive on the return object's MemoryStream property 
     using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update, leaveOpen: true)) { 
      // Write file entries into archive 
      foreach (ArchiveFile dataFile in retrievedFiles) { 
       if (dataFile.FileContent != null) { 
        // Create new ZipArchiveEntry with content 
        ZipArchiveEntry zipEntry = archive.CreateEntry(dataFile.FileName); 
        dataFile.FileContent.WriteTo(zipEntry.Open()); 
       }//end if 
      } // end foreach 
     } //end using 
    } //end using 
    return zipStream; 
}//end method 

//API to return content to user as an MVC File Content Result 
[HttpGet] 
public ActionResult DownloadFiles (string [] fileNames) { 
    FileContentResult data = new FileContentResult(GetFiles(fileNames).GetBuffer(), “application/zip”) { FileDownloadName = “files.zip” }; 
    return data; 
} //end method 

メモリストリームへの書き込み時に破損がスペースの割り当てとは何かを持っていることがあります。私は "成功"したすべてのジップ(11個以下のファイル)のサイズが259 KBであることに気付きましたが、 "失敗した"ジップ(11個以上のファイル)のサイズは517 KBでした。これは、258.5 KBの倍数であり、特に11ファイルのジップは259 KBジップになりますが、12ファイルのジップは517 KBジップになります。

何ができるかについての洞察はありますか?

+0

どのように共有できますか? – Isma

+0

残念ながら私は個人情報を含んでいません。 – crodriguez

+0

MemoryStreamを正しく使用していません。使用していないMemoryStreamを新規に作成する代わりに、新しいバイト配列を作成して返します。そのzipStream.ToArray()< - 決して適切に処分しないMemoryStreamの代わりに返さなければならないバイト配列に保存します。 –

答えて

0

私は過去に成功しましたreturn File(fileLocation, "application/zip", fileName);ここで、fileLocationはフォルダへのパス、fileNameは実際のフォルダの名前です。 ActionResultでこれを行うことができます。お使いのコントローラで

+0

はい私は別の質問の完全な例をまとめました –

+0

これは私のためにはうまくいかないでしょう。ジップは、どのファイルの組み合わせが要求されても動的に生成されるため、ディスクには格納されません。 – crodriguez

1

ASP.Net Core API Controller returns corrupted excel file

リターンこれを

return new FileResult("demo.zip", Path.Combine(sWebRootFolder, sFileName), "application/zip"); 

は、あなたのコードは、あなたがCHすることができるはず

public byte[] GetFilesAsZip (string[] arrFileNames) { 
    byte[] buffer = null; 
    using (MemoryStream zipStream = new MemoryStream()) { 
     // Retrieve files using above method 
     ArchiveFile[] retrievedFiles = GetFilesFromArchive(arrFileNames); 
     // Initialize new ZipArchive on the return object's MemoryStream property 
     using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update, leaveOpen: true)) { 
      // Write file entries into archive 
      foreach (ArchiveFile dataFile in retrievedFiles) { 
       if (dataFile.FileContent != null) { 
        // Create new ZipArchiveEntry with content 
        ZipArchiveEntry zipEntry = archive.CreateEntry(dataFile.FileName); 
        dataFile.FileContent.WriteTo(zipEntry.Open()); 
       }//end if 
      } // end foreach 
     } //end using 
     buffer = zipStream.ToArray(); 
    } //end using 
    return buffer; 
}//end method 

リファクタリング

public class FileResult : ActionResult 
    { 
     public FileResult(string fileDownloadName, string filePath, string contentType) 
     { 
      FileDownloadName = fileDownloadName; 
      FilePath = filePath; 
      ContentType = contentType; 
     } 

     public string ContentType { get; private set; } 
     public string FileDownloadName { get; private set; } 
     public string FilePath { get; private set; } 

     public async override Task ExecuteResultAsync(ActionContext context) 
     { 
      var response = context.HttpContext.Response; 
      response.ContentType = ContentType; 
      context.HttpContext.Response.Headers.Add("Content-Disposition", new[] { "attachment; filename=" + FileDownloadName }); 
      using (var fileStream = new FileStream(FilePath, FileMode.Open)) 
      { 
       await fileStream.CopyToAsync(context.HttpContext.Response.Body); 
      } 
     } 
    } 

このコードを追加します。これを

FileContentResult data = new FileContentResult(GetFiles(fileNames), “application/zip”) { FileDownloadName = “files.zip” }; 
関連する問題