使用DotNetZip通过ASP.NET MVC下载zip文件

我在文件夹中创建了一个文本文件并压缩了该文件夹并保存了@same位置以供测试。 我想在创建后直接在用户计算机上下载该zip文件。 我正在使用dotnetzip库并完成以下操作:

Response.Clear(); Response.ContentType = "application/zip"; Response.AddHeader("content-disposition", "filename=" + "sample.zip"); using (ZipFile zip = new ZipFile()) { zip.AddDirectory(Server.MapPath("~/Directories/hello")); zip.Save(Server.MapPath("~/Directories/hello/sample.zip")); } 

有人可以建议如何在用户端下载zip文件。

您可以使用控制器的File方法返回文件,如:

 public ActionResult Download() { using (ZipFile zip = new ZipFile()) { zip.AddDirectory(Server.MapPath("~/Directories/hello")); zip.Save(Server.MapPath("~/Directories/hello/sample.zip")); return File(Server.MapPath("~/Directories/hello/sample.zip"), "application/zip", "sample.zip"); } } 

如果不需要存储zip文件,则无需将其写入服务器上的文件:

 public ActionResult Download() { using (ZipFile zip = new ZipFile()) { zip.AddDirectory(Server.MapPath("~/Directories/hello")); MemoryStream output = new MemoryStream(); zip.Save(output); return File(output, "application/zip", "sample.zip"); } } 

首先,考虑一种不在服务器磁盘上创建任何文件的方法。 不好的做法。 我建议创建一个文件并将其压缩到内存中。 希望,你会发现下面的例子很有用。

 ///  /// Zip a file stream ///  ///  MemoryStream with original file  ///  Name of the file in the ZIP container  ///  Return byte array of zipped file  private byte[] GetZippedFiles(MemoryStream originalFileStream, string fileName) { using (MemoryStream zipStream = new MemoryStream()) { using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) { var zipEntry = zip.CreateEntry(fileName); using (var writer = new StreamWriter(zipEntry.Open())) { originalFileStream.WriteTo(writer.BaseStream); } return zipStream.ToArray(); } } } ///  /// Download zipped file ///  [HttpGet] public FileContentResult Download() { var zippedFile = GetZippedFiles(/* your stream of original file */, "hello"); return File(zippedFile, // We could use just Stream, but the compiler gets a warning: "ObjectDisposedException: Cannot access a closed Stream" then. "application/zip", "sample.zip"); } 

上述代码注释:

  1. 传递一个MemoryStream实例需要检查它是否打开,有效等等。我省略了它们。 我宁愿传递文件内容的字节数组而不是MemoryStream实例来使代码更健壮,但对于这个例子来说太过分了。
  2. 它没有显示如何在内存中创建所需的上下文(您的文件)。 我将引用MemoryStream类来获取指令。

只是对Klaus解决方案的修复:(因为我无法添加评论,我必须添加另一个答案!)

解决方案很棒,但对我来说它提供了损坏的zip文件,我意识到这是因为返回是在最终确定zip对象之前所以它没有关闭zip并导致损坏的zip。

所以为了解决这个问题,我们需要在使用zip块之后移动返回线,以便它可以工作。 最终结果是:

 ///  /// Zip a file stream ///  ///  MemoryStream with original file  ///  Name of the file in the ZIP container  ///  Return byte array of zipped file  private byte[] GetZippedFiles(MemoryStream originalFileStream, string fileName) { using (MemoryStream zipStream = new MemoryStream()) { using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) { var zipEntry = zip.CreateEntry(fileName); using (var writer = new StreamWriter(zipEntry.Open())) { originalFileStream.WriteTo(writer.BaseStream); } } return zipStream.ToArray(); } } ///  /// Download zipped file ///  [HttpGet] public FileContentResult Download() { var zippedFile = GetZippedFiles(/* your stream of original file */, "hello"); return File(zippedFile, // We could use just Stream, but the compiler gets a warning: "ObjectDisposedException: Cannot access a closed Stream" then. "application/zip", "sample.zip"); } 

对于那些只想从App_Data文件夹返回现有Zip文件的人(只在那里转储zip文件),在Home控制器中创建此操作方法:

  public FileResult DownLoad(string filename) { var content = XFile.GetFile(filename); return File(content, System.Net.Mime.MediaTypeNames.Application.Zip, filename); } 

Get File是一种扩展方法:

  public static byte[] GetFile(string name) { string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); string filenanme = path + "/" + name; byte[] bytes = File.ReadAllBytes(filenanme); return bytes; } 

家庭控制器索引视图如下所示:

 @model List  @foreach (var item in Model) {  } 
@Html.DisplayName("File Name") @Html.DisplayName("Last Write Time") @Html.DisplayName("Length (mb)")
@Html.ActionLink("DownLoad","DownLoad",new {filename=item.Name}) @Html.DisplayFor(modelItem => item.Name) @Html.DisplayFor(modelItem => item.LastWriteTime) @Html.DisplayFor(modelItem => item.Length)

主索引文件操作方法:

  public ActionResult Index() { var names = XFile.GetFileInformation(); return View(names); } 

GetFileInformation是一个扩展方法:

  public static List GetFileInformation() { string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); var dirInfo = new DirectoryInfo(path); return dirInfo.EnumerateFiles().ToList(); } 

创建一个返回FileResultGET FileResult控制器操作,如下所示:

 [HttpGet] public FileResult Download() { // Create file on disk using (ZipFile zip = new ZipFile()) { zip.AddDirectory(Server.MapPath("~/Directories/hello")); //zip.Save(Response.OutputStream); zip.Save(Server.MapPath("~/Directories/hello/sample.zip")); } // Read bytes from disk byte[] fileBytes = System.IO.File.ReadAllBytes( Server.MapPath("~/Directories/hello/sample.zip")); string fileName = "sample.zip"; // Return bytes as stream for download return File(fileBytes, "application/zip", fileName); }