如何在Nest.js中将Azure Blob Storage文件打包为Zip下载
在Nest.js中实现Azure Blob文件打包下载
1. 安装依赖
首先安装处理压缩包的流式工具archiver,适配Azure Blob的流操作:
npm install archiver npm install @types/archiver --save-dev
2. 改造服务层逻辑
在你的Blob存储服务中新增打包方法,通过流式操作直接将多个Azure Blob文件压缩成zip:
import { Injectable } from '@nestjs/common'; import { BlockBlobClient, ContainerClient } from '@azure/storage-blob'; import * as archiver from 'archiver'; import { PassThrough } from 'stream'; @Injectable() export class BlobStorageService { private containerClient: ContainerClient; // 省略containerClient的初始化逻辑 getBlobClient(fileName: string): BlockBlobClient { return this.containerClient.getBlockBlobClient(fileName); } async packFilesToZipStream(fileNames: string[]): Promise<PassThrough> { const zipArchive = archiver('zip', { zlib: { level: 9 } }); const outputStream = new PassThrough(); zipArchive.pipe(outputStream); // 遍历目标文件,逐个下载流并加入压缩包 for (const name of fileNames) { const blobClient = this.getBlobClient(name); const downloadRes = await blobClient.download(); zipArchive.append(downloadRes.readableStreamBody, { name }); } // 完成压缩包写入 await zipArchive.finalize(); return outputStream; } // 如果需要返回Blob对象(而非直接响应给客户端) async packFilesToBlob(fileNames: string[]): Promise<Blob> { const zipArchive = archiver('zip', { zlib: { level: 9 } }); const bufferChunks: Buffer[] = []; zipArchive.on('data', chunk => bufferChunks.push(chunk)); for (const name of fileNames) { const blobClient = this.getBlobClient(name); const downloadRes = await blobClient.download(); zipArchive.append(downloadRes.readableStreamBody, { name }); } await zipArchive.finalize(); return new Blob(bufferChunks, { type: 'application/zip' }); } }
3. 控制器层处理响应
在控制器中调用服务方法,设置正确的响应头,让客户端识别为zip文件:
import { Controller, Get, Res, Query } from '@nestjs/common'; import { Response } from 'express'; import { BlobStorageService } from './blob-storage.service'; @Controller('files') export class FilesController { constructor(private readonly blobService: BlobStorageService) {} @Get('download-zip') async downloadPackedFiles( @Query('fileNames') fileNames: string[], @Res() res: Response, ) { // 设置响应头,指定文件名和内容类型 res.setHeader('Content-Type', 'application/zip'); res.setHeader('Content-Disposition', 'attachment; filename="packed-files.zip"'); const zipStream = await this.blobService.packFilesToZipStream(fileNames); zipStream.pipe(res); } }
核心说明
- 全程采用流式处理,无需将文件下载到服务器本地,节省存储资源
PassThrough流用于桥接压缩包流和响应流,确保数据正确传递到客户端- 如果业务场景需要返回Blob对象而非直接响应,可使用
packFilesToBlob方法
内容的提问来源于stack exchange,提问作者Code The World
相关产品推荐
相关产品推荐

