通过Nest.js我们可以实现文件上传功能,这样就可以把老婆们都存到服务器里来了,上传功能需要借助multer包实现
- 安装multer及其类型声明包
npm install multer
npm install @types/multer
- 生成一个upload文件夹用于提供上传服务
nest g res upload
文件上传
设置默认选项
在upload文件夹中设置一些默认选项,通过调用MulterModule中的register方法实现。如果需要异步处理文件上传,可以使用registerAsync
import { Module } from '@nestjs/common'; import { UploadService } from './upload.service'; import { UploadController } from './upload.controller'; import { MulterModule } from '@nestjs/platform-express'; import { diskStorage } from 'multer'; import { extname, join } from 'path'; @Module({ // 通过imports的方式进行注册 imports:[MulterModule.register({ storage:diskStorage({ // 存放文件的目录 destination:join(__dirname,'../image'), // 重命名文件 filename:(req,file,callback) => { // 使用时间戳 + 文件名称的方式来存储文件 callback(null,`${new Date().getTime()}` + extname(file.originalname)) } }) })], controllers: [UploadController], providers: [UploadService], }) export class UploadModule {}
MulterModule.register接收一个配置对象,这里列出所有受支持的选项(来源:Multer中文文档)
dest or storage |
在哪里存储文件 |
fileFilter |
文件过滤器,控制哪些文件可以被接受 |
limits |
限制上传的数据 |
preservePath |
保存包含文件名的完整文件路径 |
其中,storage需要使用diskStorage函数生成,diskStorage函数同样接收一个配置对象,有两个可用的选项destination和filename。详细信息如下:
- destination用来确定文件的存储位置,其类型可以是和filename一样的函数,也可以是一个字符串。如果没有提供,存储位置将默认为操作系统的临时文件夹。
- filename用于确定文件的名称,其类型是一个接收请求信息、文件信息和回调函数的函数。如果没有设置 filename,每个文件将随机设置一个文件名并且没有扩展名
- callback的第一个参数是错误信息,第二个是返回的字符串
需要注意的是, Multer不会为文件提供任何扩展名。callback应当返回一个完整的文件名。本例中我们使用extname取出文件的扩展名(.jpg),file.originalname表示用户计算机上文件的完整名称
部署上传服务
在upload.controller.ts中使用FileInterceptor中间件进行部署,该装饰器接收一个字符串类型参数和一个配置对象,字符串要和POST请求体中包含文件的字段名称一致,配置对象和上文MulterModule.register的配置对象格式相同,不过我们这里予以省略
import { Controller, Post, UseInterceptors, UploadedFile, } from '@nestjs/common'; import { UploadService } from './upload.service'; import { CreateUploadDto } from './dto/create-upload.dto'; import { UpdateUploadDto } from './dto/update-upload.dto'; import { FileInterceptor } from '@nestjs/platform-express'; @Controller('upload') export class UploadController { constructor(private readonly uploadService: UploadService) {} @Post() // @UseInterceptors指示要注册哪个中间件 @UseInterceptors(FileInterceptor('file')) // @UploadedFile从request中取出file create(@UploadedFile() file: Express.Multer.File) { console.log(file); return true; } }
以上,如果文件上传成功则控制台会打印出文件的信息并返回true,我们可以使用ApiFox测试一下
无需关注校验信息(迫真),上传已经成功了。注意参数名一定要是file(和FileInterceptor中定义的一致)
静态目录
和express中的express.static()相同,nest.js也提供了对应方法解决创建静态目录的问题,并且非常方便
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; // 引入NestExpressApplication接口 import { NestExpressApplication } from '@nestjs/platform-express'; import { join } from 'path'; async function bootstrap() { // 传入泛型获取代码提示 const app = await NestFactory.create<NestExpressApplication>(AppModule); // 设置静态目录路径 app.useStaticAssets(join(__dirname,'..', 'public') await app.listen(3000); } bootstrap();
很简单,只需要操作main.ts即可。使用app.useStaticAssets()方法创建静态目录,该方法接收两个参数,第一个是字符串,对应服务器上的资源URL,第二个是一个配置对象,可以在里面定义虚拟路径等参数
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; // 引入NestExpressApplication接口 import { NestExpressApplication } from '@nestjs/platform-express'; import { join } from 'path'; async function bootstrap() { // 传入泛型获取代码提示 const app = await NestFactory.create<NestExpressApplication>(AppModule); // 设置静态目录路径 app.useStaticAssets(join(__dirname,'..', 'public'),{ prefix:'/nuohang', }) await app.listen(3000); } bootstrap();