如何从Blob存储批量下载文件并打包为Zip?
Blob存储多文件打包Zip下载问题
我将文件存在Blob存储里,想把文件夹里的多个文件下载并打包成Zip,但写的代码触发不了下载。相关代码如下:
最初尝试的打包代码
string zipFileName = "MyZipFiles.zip"; using (var zipOutputStream = new ZipOutputStream(HttpContext.Current.Response.OutputStream)) { zipOutputStream.SetLevel(0); HttpContext.Current.Response.BufferOutput = false; HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + zipFileName); HttpContext.Current.Response.ContentType = "application/zip"; foreach (var filePath in fileUrl) { var filename = Path.GetFileName(filePath.filename); var filebytes = filePath.filebyte.BlobByteArray; var fileEntry = new ZipEntry(Path.GetFileName(filePath.filename)) { Size = filebytes.Length }; zipOutputStream.PutNextEntry(fileEntry); zipOutputStream.Write(filebytes, 0, filebytes.Length); } zipOutputStream.Flush(); zipOutputStream.Close(); }
获取fileUrl集合的代码
foreach (var item in obj) { em = new FileUrlForbyte(); em.filename = item.FileName; em.url = objBlobHelper.GetFileByFileNameMultiple(item.ContainerName, item.SubFolderName + "/" + item.FileName, DateTime.Now.AddMinutes(2)); em.filebyte = objBlobHelper.DownloadFileByFileNameForAdobe(item.ContainerName, item.SubFolderName + "/" + item.FileName); fileUrl.Add(em); }
说明:filePath包含filename、fileurl和filebyte字段
完整API方法代码
[Route("api/Blob/getMultipleFileFromBlobByURI")] [HttpGet] public System.Web.Mvc.FileResult getMultipleFileFromBlobByURI(string containerName) { List<BlobStorageModel> obj = new JavaScriptSerializer().Deserialize<List<BlobStorageModel>>(containerName); try { BlobHelper objBlobHelper = new BlobHelper(apiPrincipal); List<FileUrlForbyte> fileUrl = new List<FileUrlForbyte>(); FileUrlForbyte em = new FileUrlForbyte(); foreach (var item in obj) { em = new FileUrlForbyte(); em.filename = item.FileName; em.url = objBlobHelper.GetFileByFileNameMultiple(item.ContainerName, item.SubFolderName + "/" + item.FileName, DateTime.Now.AddMinutes(2)); em.filebyte = objBlobHelper.DownloadFileByFileNameForAdobe(item.ContainerName, item.SubFolderName + "/" + item.FileName); fileUrl.Add(em); } // 生成Zip并下载 string zipFileName = "MyZipFiles.zip"; var fileName = string.Format("{0}_ImageFiles.zip", DateTime.Today.Date.ToString("dd-MM-yyyy") + "_1"); var tempOutPutPath = System.Web.HttpContext.Current.Server.MapPath(Url.Content("/TempImages/")) + fileName; try { using (var zipOutputStream = new ZipOutputStream(HttpContext.Current.Response.OutputStream)) { zipOutputStream.SetLevel(9); byte[] buffer = new byte[4096]; HttpContext.Current.Response.BufferOutput = false; HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + zipFileName); HttpContext.Current.Response.ContentType = "application/zip"; foreach (var filePath in fileUrl) { var filename = Path.GetFileName(filePath.filename); var filebytes = filePath.filebyte.BlobByteArray; var fileEntry = new ZipEntry(Path.GetFileName(filePath.filename)) { Size = filebytes.Length }; zipOutputStream.PutNextEntry(fileEntry); zipOutputStream.Write(filebytes, 0, filebytes.Length); } zipOutputStream.Finish(); zipOutputStream.Flush(); zipOutputStream.Close(); } byte[] finalResult = System.IO.File.ReadAllBytes(tempOutPutPath); if (System.IO.File.Exists(tempOutPutPath)) System.IO.File.Delete(tempOutPutPath); if (finalResult == null || !finalResult.Any()) throw new Exception(String.Format("No Files found with Image")); return new System.IO.File(finalResult, "application/zip", fileName); } catch (Exception) { throw; } } catch (Exception) { throw; } }
问题分析与修复方案
你的代码存在几个关键问题导致无法触发下载:
- 本地文件操作逻辑矛盾:代码里定义了
tempOutPutPath但从未向该路径写入内容,后续却尝试读取该文件,必然抛出文件不存在的异常,中断下载流程。 - Response流与FileResult冲突:你已经直接往
Response.OutputStream写入Zip数据,后续又返回FileResult,两者逻辑冲突,会导致Response输出混乱。 - Response处理不完整:写入Zip后未正确终止Response,后续代码可能干扰输出结果。
修复后的核心代码
替换API中Zip生成与返回的部分:
// 生成Zip并下载 string zipFileName = $"MyZipFiles_{DateTime.Today:dd-MM-yyyy}_1.zip"; // 清空Response,避免之前的输出干扰 HttpContext.Current.Response.Clear(); HttpContext.Current.Response.BufferOutput = false; HttpContext.Current.Response.ContentType = "application/zip"; HttpContext.Current.Response.AddHeader("Content-Disposition", $"attachment; filename=\"{zipFileName}\""); using (var zipOutputStream = new ZipOutputStream(HttpContext.Current.Response.OutputStream)) { zipOutputStream.SetLevel(9); foreach (var filePath in fileUrl) { var entryName = Path.GetFileName(filePath.filename); var filebytes = filePath.filebyte.BlobByteArray; var zipEntry = new ZipEntry(entryName) { Size = filebytes.Length, DateTime = DateTime.Now }; zipOutputStream.PutNextEntry(zipEntry); zipOutputStream.Write(filebytes, 0, filebytes.Length); zipOutputStream.CloseEntry(); } zipOutputStream.Finish(); } // 终止Response,确保输出完整 HttpContext.Current.Response.Flush(); HttpContext.Current.Response.End(); return null;
额外优化点
- 用字符串插值简化文件名拼接,同时给ZipEntry添加
DateTime属性,保留文件元数据 - 调用
CloseEntry()确保每个Zip条目正确闭合 - 提前调用
Response.Clear()清空Response,避免冗余输出干扰 - 用
Response.End()终止Response,防止后续代码执行影响下载流程
内容的提问来源于stack exchange,提问作者Swati
相关产品推荐
相关产品推荐

