Nest 文件上传 - 就是增强版的 el-upload

1. 回顾 Express 的 multer

上节我们学了 Express 的 multer:

javascript 复制代码
// Express 写法
app.post('/upload', upload.single('file'), (req, res) => {
  req.file;  // 文件
  req.body;   // 其他字段
});

Nest 怎么写?


2. Nest 文件上传 - 三步走

第 1 步:安装类型包

bash 复制代码
npm install -D @types/multer

第 2 步:写接口

typescript 复制代码
@Post('aaa')
@UseInterceptors(FileInterceptor('aaa', {
    dest: 'uploads'  // 保存目录
}))
uploadFile(
    @UploadedFile() file: Express.Multer.File,
    @Body() body
) {
    console.log('文件信息:', file);
    console.log('其他字段:', body);
}

第 3 步:前端上传

html 复制代码
<input type="file" id="fileInput" />

<script>
const fileInput = document.querySelector('#fileInput');

fileInput.onchange = async () => {
  const data = new FormData();
  data.set('aaa', fileInput.files[0]);

  await axios.post('http://localhost:3000/aaa', data);
};
</script>

3. 对比 Express

Express Nest 说明
upload.single('field') FileInterceptor('field') 单文件
upload.array('field', n) FilesInterceptor('field', n) 多文件
upload.fields([...]) FileFieldsInterceptor([...]) 多字段
upload.any() AnyFilesInterceptor() 任意文件
req.file @UploadedFile() 获取文件
req.files @UploadedFiles() 获取文件数组
req.body @Body() 获取其他字段

4. 多文件上传

后端

typescript 复制代码
@Post('bbb')
@UseInterceptors(FilesInterceptor('bbb', 3, {
    dest: 'uploads'
}))
uploadFiles(
    @UploadedFiles() files: Array<Express.Multer.File>,
    @Body() body
) {
    console.log('文件列表:', files);
}

前端

javascript 复制代码
// 传多个文件
[...fileInput.files].forEach(file => {
    data.append('bbb', file);
});

await axios.post('http://localhost:3000/bbb', data);

对比 Element Plus

html 复制代码
<el-upload
  action="/api/upload"
  :auto-upload="false"
  :on-change="handleChange"
  multiple
>
</el-upload>

5. 不同字段传不同文件

场景:头像 + 附件分开传

后端

typescript 复制代码
@Post('ccc')
@UseInterceptors(FileFieldsInterceptor([
    { name: 'avatar', maxCount: 1 },    // 头像,最多1个
    { name: 'attachments', maxCount: 3 } // 附件,最多3个
], {
    dest: 'uploads'
}))
uploadFileFields(
    @UploadedFiles() files: { avatar?: Express.Multer.File[], attachments?: Express.Multer.File[] },
    @Body() body
) {
    console.log('头像:', files.avatar);
    console.log('附件:', files.attachments);
}

前端

javascript 复制代码
const data = new FormData();
data.append('avatar', avatarFile);
data.append('attachments', file1);
data.append('attachments', file2);

await axios.post('http://localhost:3000/ccc', data);

对比 el-upload 多文件上传

html 复制代码
<el-upload
  action="/api/upload"
  :auto-upload="false"
  :file-list="fileList"
>
  <el-button>上传头像和附件</el-button>
</el-upload>

6. 任意文件上传

不知道有哪些字段会上传文件?

typescript 复制代码
@Post('ddd')
@UseInterceptors(AnyFilesInterceptor({
    dest: 'uploads'
}))
uploadAnyFiles(
    @UploadedFiles() files: Array<Express.Multer.File>,
    @Body() body
) {
    console.log('所有文件:', files);
}

7. 文件信息详解

上传成功后,file 对象包含:

typescript 复制代码
{
  fieldname: 'aaa',      // 字段名
  originalname: '1.png', // 原始文件名
  encoding: '7bit',      // 编码
  mimetype: 'image/png', // MIME 类型
  size: 1024,            // 文件大小(字节)
  destination: 'uploads', // 保存目录
  filename: 'xxx.png',   // 保存的文件名
  path: 'uploads/xxx.png' // 完整路径
}

对比前端的 file 对象

javascript 复制代码
// 前端 file 对象
{
  name: '1.png',        // 文件名
  size: 1024,           // 大小
  type: 'image/png',     // 类型
  lastModified: 1234567890
}

8. 完整流程图

kotlin 复制代码
前端                                Nest
 ───                                ───
FormData + axios    ──────────►   @UseInterceptors
     │                            FileInterceptor
     │                                   │
     │   multipart/form-data             │
     │                                   │
     │                              @UploadedFile()
     │                                   ▼
     │                              保存到磁盘
     │                                   │
     ◄────────────────────────────────────┘
   响应

9. 总结

Nest 装饰器 对应 Express 作用
FileInterceptor upload.single() 单文件上传
FilesInterceptor upload.array() 多文件上传
FileFieldsInterceptor upload.fields() 多字段多文件
AnyFilesInterceptor upload.any() 任意文件
@UploadedFile() req.file 获取单文件
@UploadedFiles() req.files 获取文件数组
@Body() req.body 获取其他字段

一句话总结

Nest 文件上传就是包装了 Express multer 的拦截器版本,用 @UseInterceptors + @UploadedFile 的方式接收文件,和前端的 el-upload 完美对应。

Express = 手写中间件 Nest = 装饰器 + 拦截器,更优雅!


觉得有帮助,点个赞再走~ 👋

相关推荐
choumou_M8 分钟前
SpringBoot_5:商品秒杀场景的并发实践(初步)
java·spring boot·后端
suaizai_25 分钟前
AI Agent如何懂你:四层能力拆解
java·前端·人工智能
invicinble36 分钟前
把握前端项目的核心(vibecoding)
前端
陈明勇40 分钟前
Go 1.27 重磅发布:泛型方法落地、分配性能跃升,JSON v2 正式可用
后端
Zane19941 小时前
create_task 和直接 await 到底有什么不一样?asyncio 的 Task、gather 与并发数量控制
后端·python
0end11 小时前
AI Agent 学习笔记(三):上下文工程(下)—— KV Cache、提示词设计与 Agent Skills
前端·aigc·ai编程
喜欢吃豆1 小时前
5 分钟,让网页里站着一个会说话的 3D 数字人
后端
CAD老兵1 小时前
在浏览器里对比 DWG/DXF 图纸 —— @mlightcad/cad-diff-viewer
前端·javascript·github
Python私教1 小时前
创业团队做管理系统,别先堆页面:我把 14 个问题做成了需求门禁
后端·python·架构
攻城有术1 小时前
专项攻克-SpringBoot启动后 Bean的实例数量问题
java·spring boot·后端