使用NestJS、Sharp处理图片时类型不匹配错误求助
NestJS图片处理Pipe类型错误修复
问题描述
使用NestJS、magic-bytes.js和Sharp编写图片验证转换Pipe时,出现以下类型错误:
Type 'Promise
[]' is missing the following properties from type 'Promise<File | File[]>': then, catch, finally, [Symbol.toStringTag]ts(2739)
移除compressedFiles的类型声明后,新错误出现:
Type 'Promise
[]' is not assignable to type 'File | File[]'
原代码如下:
import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform } from "@nestjs/common"; import { filetypemime } from "magic-bytes.js"; import * as sharp from "sharp"; @Injectable() export class ParseFile implements PipeTransform { async transform( incomingFiles: Express.Multer.File | Express.Multer.File[], metadata: ArgumentMetadata, ): Promise<Express.Multer.File | Express.Multer.File[]> { const files = Array.isArray(incomingFiles) ? incomingFiles : [incomingFiles]; const bytes = files.map((file) => new Uint8Array(file.buffer)); const fileMimetype = filetypemime(bytes); if (fileMimetype) { console.log(`File type is ${fileMimetype}`); } if (incomingFiles === undefined || incomingFiles === null) { throw new BadRequestException("Validation failed (file expected)"); } if (Array.isArray(incomingFiles) && incomingFiles.length === 0) { throw new BadRequestException("Validation failed (files expected)"); } const compressedFiles: Promise<Express.Multer.File | Express.Multer.File[]> = files.map( async (file) => await sharp(file.buffer).resize(320, 240).toFormat("webp").toBuffer(), ); return Array.isArray(incomingFiles) ? compressedFiles : compressedFiles; } }
修复方案
问题根源
files.map()返回Promise<Buffer>[],但错误地将其指定为Promise<Express.Multer.File | Express.Multer.File[]>类型,两者不兼容- Sharp转换后仅返回Buffer,未包装成Pipe要求的
Express.Multer.File对象 - 未使用
Promise.all()等待所有异步转换任务完成,直接返回了Promise数组
修复后的代码
import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform } from "@nestjs/common"; import { filetypemime } from "magic-bytes.js"; import * as sharp from "sharp"; @Injectable() export class ParseFile implements PipeTransform { async transform( incomingFiles: Express.Multer.File | Express.Multer.File[], metadata: ArgumentMetadata, ): Promise<Express.Multer.File | Express.Multer.File[]> { // 提前拦截无效请求 if (!incomingFiles) { throw new BadRequestException("Validation failed (file expected)"); } if (Array.isArray(incomingFiles) && incomingFiles.length === 0) { throw new BadRequestException("Validation failed (files expected)"); } const files = Array.isArray(incomingFiles) ? incomingFiles : [incomingFiles]; // 批量验证文件类型 const fileMimetypes = files.map(file => filetypemime(new Uint8Array(file.buffer))); fileMimetypes.forEach((mimeType, index) => { if (mimeType) { console.log(`File ${index + 1} type is ${mimeType}`); } }); // 等待所有转换完成,并包装为Multer.File对象 const compressedFiles = await Promise.all( files.map(async (file) => { const convertedBuffer = await sharp(file.buffer) .resize(320, 240) .toFormat("webp") .toBuffer(); // 更新文件属性,匹配Multer.File结构 return { ...file, buffer: convertedBuffer, mimetype: "image/webp", filename: `${file.originalname.split('.')[0]}.webp` } as Express.Multer.File; }) ); // 保持返回格式与输入一致 return Array.isArray(incomingFiles) ? compressedFiles : compressedFiles[0]; } }
关键修改点
- 将参数校验移到顶部,提前拦截无效请求
- 使用
Promise.all()等待所有异步转换完成,确保返回处理后的文件而非Promise数组 - 将Sharp返回的Buffer重新包装成
Express.Multer.File对象,更新buffer、mimetype、filename等核心属性 - 修复文件类型验证逻辑,支持批量文件的类型识别
- 保证返回格式与输入一致:单个文件输入返回单个文件,数组输入返回数组
内容的提问来源于stack exchange,提问作者lucius0
相关产品推荐
相关产品推荐

