NestJS中实现上传图片自动压缩的方案求助(不限制上传大小)
NestJS 图片自动压缩Pipe实现方案
针对你当前的图片上传路由,无需限制上传大小,通过自定义Pipe实现自动压缩的可行方案如下:
1. 安装高性能图片处理依赖
使用sharp库处理图片,它在Node.js环境下内存占用低、处理速度快,适合生产环境:
npm install sharp # 或 yarn add sharp
2. 实现图片压缩Pipe
这个Pipe会拦截上传后的文件对象,对图片进行压缩并更新文件信息:
import { PipeTransform, Injectable, BadRequestException, ArgumentHost } from '@nestjs/common'; import { Express } from 'express'; import * as sharp from 'sharp'; @Injectable() export class ImageCompressionPipe implements PipeTransform<Express.Multer.File> { async transform(file: Express.Multer.File, context: ArgumentHost): Promise<Express.Multer.File> { // 二次校验图片类型(确保fileFilter生效) if (!file.mimetype.startsWith('image/')) { throw new BadRequestException('仅支持图片文件'); } // 从请求参数获取自定义压缩配置(可选) const request = context.switchToHttp().getRequest(); const targetWidth = parseInt(request.query.width) || 1920; // 默认宽1920px,等比缩放 const quality = parseInt(request.query.quality) || 80; // 默认质量80 try { // 读取原文件并压缩 const compressedBuffer = await sharp(file.path) .resize({ width: targetWidth, withoutEnlargement: true }) // 不放大小于目标尺寸的图片 .jpeg({ quality }) .png({ quality }) .webp({ quality }) // 支持webp格式自动压缩 .toBuffer(); // 将压缩后的内容覆盖原文件(也可生成新文件,见下方说明) await sharp(compressedBuffer).toFile(file.path); // 更新文件对象的大小信息 file.size = compressedBuffer.length; return file; } catch (error) { throw new BadRequestException('图片压缩失败'); } } }
可选:生成新压缩文件而非覆盖原文件
如果需要保留原上传文件,可修改Pipe内的写入逻辑:
// 生成带压缩标识的新文件名 const [name, ext] = file.filename.split('.'); const compressedFilename = `${name}-compressed.${ext}`; const compressedPath = `${file.destination}/${compressedFilename}`; // 写入新文件 await sharp(compressedBuffer).toFile(compressedPath); // 更新文件对象信息 file.filename = compressedFilename; file.path = compressedPath; file.size = compressedBuffer.length;
3. 在路由中使用压缩Pipe
直接在@UploadedFile()装饰器中加入自定义Pipe即可:
@Post('upload/banner/:postId') @UseInterceptors( FileInterceptor('file', { storage: diskStorage({ destination: './files/posts/banners', }), fileFilter: imageFileFilter, }), ) async uploadAnonymousPostBanner( @UploadedFile(ImageCompressionPipe) file: Express.Multer.File, @CurrentUserCookie('userId') userId: string, @Param('postId') postId: string, @Query('postCode') postCode:string ) { console.log(file); // 此时file已完成压缩,size为压缩后大小 const uploadImgFile = await this.postsService.uploadPostBannerImg( userId, postId, file.filename, postCode ); return uploadImgFile; }
关键说明
- 压缩参数可根据业务需求调整:比如固定尺寸、动态接收前端参数、强制转换为webp格式以获得更高压缩比。
sharp会自动处理不同图片格式,无需额外判断格式类型。- 确保文件存储目录具备写入权限,避免压缩后无法写入文件。
内容的提问来源于stack exchange,提问作者INVISIBLE BOY
相关产品推荐
相关产品推荐

