使用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"); }
上述代码注释:
- 传递一个
MemoryStream
实例需要检查它是否打开,有效等等。我省略了它们。 我宁愿传递文件内容的字节数组而不是MemoryStream
实例来使代码更健壮,但对于这个例子来说太过分了。 - 它没有显示如何在内存中创建所需的上下文(您的文件)。 我将引用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 @Html.DisplayName("File Name") @Html.DisplayName("Last Write Time") @Html.DisplayName("Length (mb)") @foreach (var item in Model) { @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(); }
创建一个返回FileResult
的GET
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); }
- 撤消ASP.NET Identity 2.0中UserTokenProvider生成的令牌
- 通过VS 2015 RC进行非Azure部署
- 我是如何做的如果在MVC5中通过函数validation
- 在用Identity注册时为用户设置角色的正确方法
- Azure AD B2C – 角色管理
- 如何将MVC 5身份validation添加到Unity IoC?
- Identity 2.0:创建自定义ClaimsIdentity例如:User.Identity.GetUserById (int id)for Per Request Validation
- Google的间歇性ASP.NET oAuth问题,AuthenticationManager.GetExternalIdentityAsync返回null
- ASP.NET MVC 5中的DateCreated和DateModified