D16 要去实现文件上传的功能,在应用的数据库里需要存储用户上传的文件相关的信息。使用 FileInterceptor 这个拦截器可以处理请求里的文件。用 UploadedFile 这个装饰器可以得到上传的文件相关的数据。
@Post() @UseInterceptors(FileInterceptor('file')) async store( @UploadedFile() data: FileDto ) { return await this.fileService.store(data); }
在客户端上传文件的时候,请求应该设置成 Multipart form,里面添加一个 file 字段,它的值就是要上传的文件。给 FileInterceptor 拦截器提供的参数值是 file ,所以上传的时候就需要包含一个叫 file 的字段 。
相关的配置:
MulterModule.register({ dest: './uploads', fileFilter: (req, file, callback) => { const mimetypes = [ 'image/png', 'image/jpg' ]; const allowed = mimetypes.some(type => type === file.mimetype); if (allowed) { callback(null, true); } else { callback(new BadRequestException('不支持上传此类型的文件。'), false); } } })
在自己创建的 File 模块里要导入 MulterModule 模块,并且要配置一下它。比如用 dest 属性设置一下上传的文件存储的路径。还可以用 fileFilter 来过滤一下要上传的文件。
上传的文件相关的信息可以存储到数据库里,文件实体可以像下面这样:
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; @Entity() export class File { @PrimaryGeneratedColumn() id: number; @Column() originalname: string; @Column() filename: string; @Column() mimetype: string; @Column() size: number; }
定义接口可以提供文件的访问:
@Get('serve/:id') async serve( @Param('id', ParseIntPipe) id: number, @Res() res: Response ) { const file = await this.fileService.show(id); res.sendFile(file.filename, { root: 'uploads', headers: { 'Content-type': file.mimetype } }); }