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

如何将Azure Blob Storage中的文件写入ZipArchive对象?

问题描述

我正在编写一个方法,用于将Azure Blob Storage中的文件打包成Zip归档,但不清楚如何将Blob文件写入到Zip中。当前代码里不知道怎么把Blob对象传入CreateEntryFromFile方法,不确定是否需要创建单独的字节数组流?

附上当前代码:

public async Task<System.IO.File> CreateLoanFilesZip(string loanFileId)
{
    var appList = _unitOfWork.Applications.GetByLoanFile(loanFileId);
    if (appList == null)
    {
        return null;
    }

    string connection = _appConfig.AzureStorageConnection;
    string containerName = _appConfig.AzureStorageContainer;
    
    //create azure service/container client
    var serviceClient = new BlobServiceClient(connection);
    var container = serviceClient.GetBlobContainerClient(containerName);
    BlobClient blob;

    //loop each row in list of loan file applications
    foreach (var app in appList)
    {
        //get list of files from documents repo by application
        var fileList = _unitOfWork.Documents.GetListByApplication(app.ApplicationId);
        if (fileList != null)
        {
            //create a zip file with loan number and application id?
            using (var memoryStream = new MemoryStream())
            {
                using (var zip = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
                {
                    foreach(var file in fileList)
                    {
                        blob = container.GetBlobClient(file.UniqueDocumentName);
                        ??--> do I need to stream the blob into the zip??
                        zip.CreateEntryFromFile(file.UniqueDocumentName, blob);
                    }
                }

                memoryStream.Position = 0;
                return File(memoryStream, "application/zip", "application-file-download.zip");
            }
        }

    }
}
解决方案

核心问题说明

CreateEntryFromFile方法仅适用于本地文件路径,无法直接传入Azure Blob对象。正确的做法是通过流操作,将Blob的内容直接写入Zip归档的条目流中,不需要额外的字节数组流(直接用内存流和条目流即可)。

另外你的代码还有几个需要修正的点:

  • 返回值System.IO.File不合适,ASP.NET场景下应返回FileStreamResult;
  • 方法标记了async但内部未使用await,需将异步操作改为await调用;
  • 当前逻辑会在处理第一个app的文件后直接return,导致只打包第一个应用的文件,需调整循环结构。

修改后的完整代码

// ASP.NET Core场景下,返回值应为IActionResult
public async Task<IActionResult> CreateLoanFilesZip(string loanFileId)
{
    var appList = _unitOfWork.Applications.GetByLoanFile(loanFileId);
    if (appList == null || !appList.Any())
    {
        return NotFound();
    }

    string connection = _appConfig.AzureStorageConnection;
    string containerName = _appConfig.AzureStorageContainer;
    
    var serviceClient = new BlobServiceClient(connection);
    var container = serviceClient.GetBlobContainerClient(containerName);

    // 将内存流和ZipArchive移到外层,确保所有应用的文件都能加入同一个Zip
    using (var memoryStream = new MemoryStream())
    {
        using (var zip = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
        {
            foreach (var app in appList)
            {
                var fileList = _unitOfWork.Documents.GetListByApplication(app.ApplicationId);
                if (fileList == null || !fileList.Any())
                {
                    continue;
                }

                foreach(var file in fileList)
                {
                    var blobClient = container.GetBlobClient(file.UniqueDocumentName);
                    if (!await blobClient.ExistsAsync())
                    {
                        // Blob不存在时可跳过或抛出异常,根据业务需求处理
                        continue;
                    }

                    // 创建Zip条目,可自定义条目名称(比如加上应用ID作为子文件夹)
                    var zipEntry = zip.CreateEntry($"{app.ApplicationId}/{file.FileName}");

                    // 打开条目的写入流,直接将Blob内容复制进去
                    using (var entryStream = zipEntry.Open())
                    {
                        await blobClient.DownloadToStreamAsync(entryStream);
                    }
                }
            }
        }

        memoryStream.Position = 0;
        // 返回Zip文件,文件名可根据业务自定义
        return File(memoryStream, "application/zip", $"loan-files-{loanFileId}.zip");
    }
}

关键修改点说明

  • 替换CreateEntryFromFile为CreateEntry:创建Zip条目后,通过zipEntry.Open()获取条目的写入流;
  • 异步流复制:使用blobClient.DownloadToStreamAsync(entryStream)直接将Blob内容写入Zip条目流,无需中间字节数组;
  • 调整循环结构:将内存流和ZipArchive的创建移到外层循环,确保所有应用的文件都能加入同一个Zip;
  • 完善边界处理:增加Blob存在性检查、空列表判断,避免空引用异常;
  • 修正返回类型:使用ASP.NET标准的IActionResult返回FileStreamResult,符合Web API的返回规范。

内容的提问来源于stack exchange,提问作者Ryan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:20:47