如何将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
相关产品推荐
相关产品推荐

