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


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

相关推荐
AI大模型-小华7 分钟前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
立心者01 小时前
SpringBoot中使用TOTP实现MFA(多因素认证)
java·spring boot·后端
AskHarries2 小时前
SEO 页面怎么生成
后端
做前端的娜娜子2 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
爱吃牛肉的大老虎2 小时前
Rust对象之结构体,枚举,特性
开发语言·后端·rust
石榴2 小时前
NestJS 的请求到底经过了什么:装饰器、守卫、拦截器、管道与中间件如何配合
后端
小帅不太帅2 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
Gopher_HBo3 小时前
moby-client客户端
后端
jarvisuni3 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法