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 = 装饰器 + 拦截器,更优雅!


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

相关推荐
ZC跨境爬虫2 小时前
海南大学交友平台开发实战 day10(后端向前端输出_前端读取数据全流程联调+日志调试落地)
前端·python·sqlite·html·状态模式
xiaotao1312 小时前
CSS中的Grid 布局
前端·css
cc_heart2 小时前
antdv-next/x:面向 Vue 的 AI 组件体系
前端·javascript·vue.js
竹林8182 小时前
RainbowKit快速集成多链钱包连接:从“一键连接”到“多链切换”的实战踩坑
前端·javascript
用户81274828151202 小时前
android使用uinput节点任意注入鼠标事件-重学安卓input子系统
前端
0xDevNull2 小时前
Spring Boot 3.x WebSocket 实战教程
spring boot·后端·websocket
用户69371750013842 小时前
AI来了,同事们的效率为什么差这么多?
android·前端·ai编程
凡小烦2 小时前
从定制化页签tab到compose列表使用
android·前端
neoooo2 小时前
Spring AI MCP Server 开发指南
人工智能·后端·mcp