将文件作为压缩文件下载到ASP.NET MVC中的损坏的zip文件中

问题描述:

我有一台托管大型XML文件存档的服务器,并且API在压缩文件中检索请求的文件。如果我选择大约11个或更少的文件,则zip返回正常。如果我检索到更多,我收到试图打开压缩时出现以下错误:“Windows无法打开该文件夹压缩(zipped)文件夹是无效 ”将文件作为压缩文件下载到ASP.NET MVC中的损坏的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,其中一些较大的尝试压缩文件的大小为1034 KB。由于太巧妙,这些都是258.5 KB的倍数,尤其是因为11个文件的zip文件导致259 KB的zip文件,而12个文件的zip文件导致517 KB zip文件。

任何洞察它可能是什么?

+0

你能不能共享XML文件? – Isma

+0

不幸的是,我不能,他们包含私人信息。 – crodriguez

+0

您没有正确使用MemoryStream。而不是在使用之外新建MemoryStream,新建一个字节数组并返回。它的zipStream.ToArray()

我已经在过去做过成功return File(fileLocation, "application/zip", fileName);其中fileLocation是文件夹的路径,fileName是实际文件夹的名称。你可以在你的ActionResult中这样做。在您的控制器

+0

是的,我把另一个问题的完整例子放在一起 –

+0

恐怕这不适合我。拉链不会存储在磁盘上,因为它们是从请求的任何文件组合动态生成的。 – crodriguez

ASP.Net Core API Controller returns corrupted excel file

回报这个

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

添加以下代码

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); 
      } 
     } 
    } 

你的代码重构

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 

你应该能够CH ange这到

FileContentResult data = new FileContentResult(GetFiles(fileNames), “application/zip”) { FileDownloadName = “files.zip” };