You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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;
    }
}

问题分析与修复方案

你的代码存在几个关键问题导致无法触发下载:

  1. 本地文件操作逻辑矛盾:代码里定义了tempOutPutPath但从未向该路径写入内容,后续却尝试读取该文件,必然抛出文件不存在的异常,中断下载流程。
  2. Response流与FileResult冲突:你已经直接往Response.OutputStream写入Zip数据,后续又返回FileResult,两者逻辑冲突,会导致Response输出混乱。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 18:15:40