前言
文件上传是每个项目都会用到的功能,NestJS在实现文件上传时,有TypeScript的强类型优势,确保代码安全稳定;语法十分的简洁,装饰器API如@UploadedFile()
简化上传逻辑;支持自定义中间件增强功能,如验证和转换;其性能出色,尤其适合高并发场景;并且,NestJS与云存储服务的友好集成,使文件管理更加便捷;丰富的插件生态系统提供了更多扩展可能,进一步优化了开发体验。这些特点使得NestJS成为实现高效、安全文件上传的理想选择。
简单的文件上传
创建nestjs的项目的步骤这里就不做介绍了可以看我的《??超简单!!nestJS+jwt实现登录》这篇文章。文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
- 执行指令:
nest g res uploads --no-spec
, 一直按回车键 - 安装 Multer typings 包:
npm i -D @types/multer
, 这样就可以有类型支持了
在uploads/uplods.controller.ts中将代码修改如下文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
ts
import {
Controller,
Post,
UploadedFile,
UseInterceptors,
} from '@nestjs/common';
import { UploadsService } from './uploads.service';
import { FileInterceptor } from '@nestjs/platform-express';
@Controller('uploads')
export class UploadsController {
constructor(private readonly uploadsService: UploadsService) {}
@Post()
@UseInterceptors(FileInterceptor('file', { dest: 'uploads' }))
upload(@UploadedFile() file: Express.Multer.File) {
console.log(file.path);
return 0;
}
}
@UseInterceptors
: 使用拦截器,里面传一个拦截器函数就行了
@@UseInterceptors
: 文件拦截器第一个参数是字段名第二参数是一个对象,dest是文件存放的位置,这个文件夹会自动创建。文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
我们在apifox里面测试一下:文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
可见已经正确的将文件的路径打印出来了。至此简单的文件上传已经完成了。文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
文件验证
只允许图片上传
实现
将代码修改如下:文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
ts
import {
BadRequestException,
Controller,
Post,
UploadedFile,
UseInterceptors,
} from '@nestjs/common';
import { UploadsService } from './uploads.service';
import { FileInterceptor } from '@nestjs/platform-express';
import * as path from 'path';
@Controller('uploads')
export class UploadsController {
constructor(private readonly uploadsService: UploadsService) {}
@Post()
@UseInterceptors(
FileInterceptor('file', {
dest: 'uploads',
fileFilter(request, file, cal) {
const ext = path.extname(file.originalname);
if (['.jpg', '.png', '.jpeg'].includes(ext)) {
return cal(null, true);
} else {
return cal(new BadRequestException('文件格式错误'), false);
}
},
}),
)
upload(@UploadedFile() file: Express.Multer.File) {
console.log(file.path);
return 0;
}
}
文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
以上代码中新增了一个fileFilter函数,里面的参数主要看file
和cal
, file
就是传来的文件cal
就是一个回调函数,如果ext在定义的文件后缀的数组中的时候第一个参数是null第二个参数是true否则第一个参数是一个异常对象第二个参数是false。文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
在apifox里面测试一下,这里我先上传一个压缩文件文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15602.html
显然返回报错信息了
试一下图片就正常返回了
可见我们的文件类型校验生效了,但是在装饰器里面写这么一坨校验的代码实在是不够美观,而且复用性也不强,我们可以封装一个聚合装饰器。
代码改造
创建custom-dec/custom.decorator.ts,新增如下代码:
ts
import { Controller, Post, UploadedFile } from '@nestjs/common';
import { UploadsService } from './uploads.service';
import { FileUpload } from 'src/custom-dec/custom.decorator';
@Controller('uploads')
export class UploadsController {
constructor(private readonly uploadsService: UploadsService) {}
@FileUpload(['.jpeg', '.png'])
@Post()
upload(@UploadedFile() file: Express.Multer.File) {
console.log(file.path);
return 0;
}
}
这段代码看似很多其实就是之前UseInterceptors装饰器整个剪切过来直接当参数放在applyDecorators函数里面,然后在外面套一个FileUpload函数,这个函数名随意,参数是文件类型,返回了applyDecorators执行结果。
改造upload路由
ts
import { Controller, Post, UploadedFile } from '@nestjs/common';
import { UploadsService } from './uploads.service';
import { FileUpload } from 'src/custom-dec/custom.decorator';
@Controller('uploads')
export class UploadsController {
constructor(private readonly uploadsService: UploadsService) {}
@FileUpload(['.jpeg', '.png'])
@Post()
upload(@UploadedFile() file: Express.Multer.File) {
console.log(file.path);
return 0;
}
}
这里将之前的UseInterceptors装饰器改成了我们自定义的聚合装饰器,并且文件类型自定义穿进去。 在apifox里面测试一下,先用不是图片的文件:
上传一个图片:
可见改造之后的代码是没有问题的,并且理由部分的代码简洁了许多。
图片大小限制
很简单,就是增加一个属性,这里限制最大为10m
由于我没有比10m大的图片所以我把图片类型限制去掉,上传一个压缩包发现大小限制生效了,在apifox里测试一下:
评论