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


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

相关推荐
9523614 小时前
MyBatis
后端·spring·mybatis
ZC跨境爬虫16 小时前
跟着 MDN 学 HTML day_9:(信件语义标记)
前端·css·笔记·ui·html
前端老石人17 小时前
HTML 字符引用完全指南
开发语言·前端·html
幼儿园技术家17 小时前
前端如何设计权限系统(RBAC / ABAC)?
前端
uzong17 小时前
9 种 RAG 架构,每位 AI 开发者必学:完整实战指南
后端
小江的记录本18 小时前
【Kafka核心】架构模型:Producer、Broker、Consumer、Consumer Group、Topic、Partition、Replica
java·数据库·分布式·后端·搜索引擎·架构·kafka
止语Lab18 小时前
从手动到框架:Go DI 演进的三个拐点
开发语言·后端·golang
前端摸鱼匠19 小时前
Vue 3 的v-bind合并行为:讲解v-bind与普通属性合并的规则
前端·javascript·vue.js·前端框架·ecmascript
REDcker19 小时前
浏览器端Web程序性能分析与优化实战 DevTools指标与工程清单
开发语言·前端·javascript·vue·ecmascript·php·js
donecoding20 小时前
一个 sudo 引发的血案:npm 全局包权限错乱彻底修复
前端·node.js·前端工程化