NestJS上传Excel解析时file.buffer读取报错解决方案
问题根因
file.buffer读取时报错,由两处代码错误直接导致:
- 上传接口重复注册了两次
FileInterceptor拦截器:一个传入自定义multer配置,一个无任何配置,后者会覆盖前者的配置生效 - 自定义multer配置使用
diskStorage磁盘存储模式:该模式下Multer会将上传文件写入本地磁盘,返回的file对象仅包含文件存储路径、原始文件名等元信息,不会生成buffer二进制字段。file.buffer仅在Multer使用默认memoryStorage内存存储模式时才会存在。
修复步骤
- 删除接口上重复的无配置
@UseInterceptors(FileInterceptor('file'))装饰器,仅保留传入multerOptions的拦截器 - 根据业务需求调整存储配置:
- 如果不需要在服务端持久化存储原始上传文件,直接将multer的存储模式改为
memoryStorage,即可直接读取file.buffer做Excel解析 - 如果需要持久化存储原始文件,保留
diskStorage配置,改为通过文件系统接口读取本地存储的文件内容后再做解析
- 如果不需要在服务端持久化存储原始上传文件,直接将multer的存储模式改为
- (可选优化)原文件类型校验的正则匹配逻辑存在误判风险,建议改为扩展名+MIME类型双重精确校验,同时给文件大小配置加默认值,避免环境变量未定义导致配置异常。
修复后代码示例
上传接口代码
@Post('upload') @UseInterceptors(FileInterceptor('file', multerOptions)) UploadExcelFile(@UploadedFile() file: Express.Multer.File) { console.log("Hello") console.log(file); const workBook: XLSX.WorkBook = XLSX.read(file.buffer, { type: 'buffer', cellDates: true, cellNF: false, }); const sheetName = workBook?.SheetNames[0]; const sheet: XLSX.WorkSheet = workBook.Sheets[sheetName]; const jsonData: FileUploadDto[] = XLSX.utils.sheet_to_json(sheet, { dateNF: 'YYYY-MM-DD', }); // 后续补充字段校验、入库逻辑 console.log(jsonData); // return this.usersService.processFile(file); }
multer配置(内存存储模式,适配buffer直接读取)
import { extname } from 'path'; import { memoryStorage } from 'multer'; import { HttpException, HttpStatus } from '@nestjs/common'; export const multerOptions = { limits: { // 增加默认值,避免环境变量未读取到导致大小限制异常 fileSize: +process.env.MAX_FILE_SIZE || 5 * 1024 * 1024, }, fileFilter: (_req: any, file: any, callback: any) => { const allowedExts = ['.jpg','.jpeg','.png','.gif','.pdf','.msg','.eml','.docx','.doc','.xlsx','.xls']; const fileExt = extname(file.originalname).toLowerCase(); const allowedMimes = [ 'image/jpeg','image/png','image/gif','application/pdf', 'application/vnd.ms-outlook','message/rfc822', 'application/msword','application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.ms-excel','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ]; if (allowedExts.includes(fileExt) && allowedMimes.includes(file.mimetype)) { callback(null, true); } else { callback( new HttpException( `Unsupported file type ${fileExt}`, HttpStatus.BAD_REQUEST ), false ); } }, // 替换为内存存储,自动生成file.buffer字段 storage: memoryStorage(), };
若需保留磁盘存储逻辑,无需修改multer配置,将接口内读取buffer的逻辑替换为磁盘文件读取即可:
import * as fs from 'fs/promises'; // 接口内获取文件后读取内容 const fileBuffer = await fs.readFile(file.path); const workBook: XLSX.WorkBook = XLSX.read(fileBuffer, { type: 'buffer', cellDates: true, cellNF: false, }); // 后续Excel解析逻辑与之前一致
上传解析对应DTO
import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsString, MaxLength } from 'class-validator'; export class FileUploadDto { @IsString() @IsNotEmpty() @MaxLength(25) displayName: string; @IsString() @IsNotEmpty() @MaxLength(25) email: string; @IsString() @IsNotEmpty() @MaxLength(50) role: string; }
问题复现材料
- 接口报错截图:

- 测试Excel文件内容:

内容的提问来源于stack exchange,提问作者Shruti sharma
相关产品推荐
相关产品推荐

