NestJS上传CSV文件时持续出现415不支持媒体类型错误求助
问题描述
我正在编写支持CSV文件上传的NestJS接口,尝试了两种实现方式:
方式一:
@Post('/bulk') @UseInterceptors(FileInterceptor('file')) uploadFile(@UploadedFile() file: Express.Multer.File) { console.log(file); }
方式二:
@Post('/bulk') uploadFile( @Body(new ParseArrayPipe({ items: CreatePlaceDto })) dtos: CreatePlaceDto[], @Req() request: CrudRequest) { console.log(dtos); }
但两种方式均返回415错误,错误信息如下:
{ "statusCode": 415, "code": "FST_ERR_CTP_INVALID_MEDIA_TYPE", "error": "Unsupported Media Type", "message": "Unsupported Media Type: multipart/form-data; boundary=--------------------------520916914275921544205184" }
我通过Postman测试时,已在请求头设置content-type为"multipart/form-data",并在form-data体中以"file"为键上传CSV文件。请问该问题原因是什么?恳请相关解决建议!
原因分析与解决建议
核心原因
- 方式二逻辑不匹配:
@Body()+ParseArrayPipe是用来解析application/json类型的请求体,而文件上传依赖multipart/form-data格式,两者完全不兼容,所以方式二从根本上不适用文件上传场景。 - 方式一缺失必要配置:NestJS的文件上传功能依赖
multer库,若未正确安装依赖或在模块中完成配置,框架无法解析multipart/form-data请求,直接抛出415错误。
解决步骤
针对方式一(正确的文件上传实现)
- 安装依赖包:
执行命令安装multer及对应的类型定义:npm install @nestjs/platform-express multer npm install -D @types/multer - 模块中配置Multer:
在对应功能模块(比如PlaceModule)中导入MulterModule,可设置文件临时存储路径:import { Module } from '@nestjs/common'; import { MulterModule } from '@nestjs/platform-express'; import { diskStorage } from 'multer'; import { extname } from 'path'; import { PlaceController } from './place.controller'; @Module({ imports: [ MulterModule.register({ storage: diskStorage({ destination: './uploads', // 需提前创建该目录 filename: (req, file, cb) => { const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9); cb(null, file.fieldname + '-' + uniqueSuffix + extname(file.originalname)); }, }), }), ], controllers: [PlaceController], }) export class PlaceModule {} - 修正Postman请求设置:
- 不要手动设置
Content-Type为multipart/form-data,Postman会在选择form-data并添加文件后自动生成带正确boundary的请求头,手动设置反而可能导致格式不匹配。 - 确认form-data中的键名与
FileInterceptor('file')的参数一致(即file)。
- 不要手动设置
额外拓展:解析CSV内容
如果需要把上传的CSV文件内容转换为CreatePlaceDto数组,可以使用csv-parser库处理:
- 安装依赖:
npm install csv-parser - 在控制器中处理文件内容:
import * as csvParser from 'csv-parser'; import { createReadStream } from 'fs'; import { CreatePlaceDto } from './dto/create-place.dto'; @Post('/bulk') @UseInterceptors(FileInterceptor('file')) async uploadFile(@UploadedFile() file: Express.Multer.File) { const results: CreatePlaceDto[] = []; await new Promise((resolve, reject) => { createReadStream(file.path) .pipe(csvParser()) .on('data', (data) => results.push(data as CreatePlaceDto)) .on('end', resolve) .on('error', reject); }); console.log(results); // 后续业务逻辑处理 }
内容的提问来源于stack exchange,提问作者Kaisin Li
相关产品推荐
相关产品推荐

