文件上传
为了处理文件上传,Nest 为 Express
提供了一个基于 multer
中间件包的内置模块。 Multer 处理以 multipart/form-data
格式发布的数据,该格式主要用于通过 HTTP POST 请求上传文件。 该模块是完全可配置的,你可以根据你的应用要求调整其行为。
警告
Multer
无法处理不支持的多部分格式 (multipart/form-data)
的数据。 另请注意,此包与 FastifyAdapter
不兼容。
为了更好的类型安全,让我们安装 Multer typings 包:
npm i -D @types/multer
单文件上传
要上传单个文件,只需将 FileInterceptor()
拦截器绑定到路由处理程序并使用 @UploadedFile()
装饰器从 request
中提取 file。
import { Controller, FileTypeValidator, Get, MaxFileSizeValidator, ParseFilePipe, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { UserService } from './user.service';
import { FileInterceptor } from '@nestjs/platform-express';
import { createWriteStream } from 'fs';
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) { }
@Post("uploadOne")
@UseInterceptors(FileInterceptor('file'))
uploadOne(@UploadedFile() file: any) {
const fileName = file.originalname
const writeStream = createWriteStream(`src/public/upload/${fileName}`)
writeStream.write(file.buffer)
}
}
现在,你可以上传任意类型的文件,并且大小不受限制
验证
通常,验证传入的文件元数据很有用,例如文件大小或文件 mime 类型。 为此,你可以创建自己的 管道 并将其绑定到使用 UploadedFile
装饰器注释的参数。 下面的示例演示了如何实现基本的文件大小验证器管道:
Nest 提供了一个内置的管道来处理常见的用例并促进/标准化新的添加。 该管道称为 ParseFilePipe
,你可以按如下方式使用它:
import { Controller, FileTypeValidator, Get, MaxFileSizeValidator, ParseFilePipe, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { UserService } from './user.service';
import { FileInterceptor } from '@nestjs/platform-express';
import { createWriteStream } from 'fs';
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) { }
@Post("uploadOne")
@UseInterceptors(FileInterceptor('file'))
uploadOne(@UploadedFile(new ParseFilePipe({
validators: [
new MaxFileSizeValidator({ maxSize: 1000 }),
new FileTypeValidator({ fileType: 'image' }),
]
})) file: any) {
const fileName = file.originalname
const writeStream = createWriteStream(`src/public/upload/${fileName}`)
writeStream.write(file.buffer)
}
}
通过以上限制,你只能上传图片类型的文件,并且大小不能超过1000
上传文件名乱码问题解决
假如你上传的文件名称是中文命名,很大程度上后台接收的file.originalname
是乱码的,此时你可以使用iconv-lite
库进行解决乱码
npm i --save iconv-lite
使用
const iconv = require('iconv-lite');
const fileName = iconv.decode(Buffer.from(file.originalname, 'binary'), 'utf-8')
多文件上传
要上传多个文件(所有文件都具有不同的字段名称键),请使用 FileFieldsInterceptor()
装饰器。 这个装饰器有两个参数:
uploadedFields
: 一个对象数组,其中每个对象指定一个必需的 name 属性,其中一个字符串值指定一个字段名称,如上所述,以及一个可选的maxCount
属性,如上所述options
: 可选的MulterOptions
对象,如上所述
使用 FileFieldsInterceptor()
时,使用 @UploadedFiles()
装饰器从 request 中提取文件。
import { Controller, Post, UploadedFiles, UseInterceptors } from '@nestjs/common';
import { UserService } from './user.service';
import { FileFieldsInterceptor } from '@nestjs/platform-express';
import { createWriteStream } from 'fs';
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) { }
@Post("uploadMore")
@UseInterceptors(FileFieldsInterceptor([
{ name: 'file', maxCount: 9 },
{ name: 'image', maxCount: 1 },
{ name: 'video', maxCount: 9 },
{ name: 'audio', maxCount: 9 },
]))
uploadOne(@UploadedFiles() file: any) {
console.log(file);
//注意把不同文件放进不同的文件夹
}
}