nest文件上传

131 阅读2分钟

依赖安装

npm i platform-express multer

module配置

  • 文件存储目录为项目根目录下的uploads文件夹
import { Module } from '@nestjs/common';
import { FileController } from './file.controller';
import { MulterModule } from '@nestjs/platform-express';
import { diskStorage } from 'multer';

@Module({
  imports: [
    MulterModule.registerAsync({
      useFactory() {
        return {
          storage: diskStorage({
            //文件储存位置
            destination: 'uploads',
            //文件名定制
            filename: (req, file, callback) => {
              const name = new Date().getTime() + file.originalname
              callback(null, name)
            },
          }),
        }
      },
    }),
  ],
  controllers: [FileController],
})
export class FileModule {}

上传接口(controller)

  • 接口:post -> /file/upload
  • 最大允许上传10M,限制上传文件类型为image图片类型
import {
  Controller,
  Get,
  Post,
  UploadedFile,
  UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';

@Controller('file')
export class FileController {
  @Post('upload')
  @UseInterceptors(FileInterceptor('file', {
    limits: {
      fileSize: 1024 * 1024 * 10,
    },
    fileFilter: (req: any, file: any, callback: (error: Error | null, acceptFile: boolean) => void) => {
        if (['image'].some(mime => file.mimetype.includes(mime))) {
            callback(null, true)
        } else {
            callback(new UnsupportedMediaTypeException('文件类型错误11'), false)
        }
    },
  }))
  fileUpload(@UploadedFile() file) {
    return {
      code: 200,
      file,
    };
  }
}

  • 到这,一个nest的上传接口就ok了,下面做一下优化

装饰器优化

  • 将@UseInterceptors(FileInterceptor('file'))封装到一个自定已装饰器中让调用更加方便
  • 将文件类型校验封装

自定义装饰器

src目录下执行命令

nest g decorator file-filter
  • src/file-filter
import {  UnsupportedMediaTypeException, UseInterceptors, applyDecorators } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';

/**
 * 自定义装饰器
 * 
 * @param fieldName 
 * @param options 
 * @returns 
 */
export const FileFilter = (fieldName = 'file', options: MulterOptions = {}) => {
    return applyDecorators(UseInterceptors(FileInterceptor(fieldName, options)))
};

/**
 * 文件类型方法封装
 * 
 * @param types 
 * @returns 
 */
export function FiletypeFilter(...types: string[]) {
    return (req: any, file: any, callback: (error: Error | null, acceptFile: boolean) => void) => {
        if (types.some(mime => file.mimetype.includes(mime))) {
            callback(null, true)
        } else {
            callback(new UnsupportedMediaTypeException('文件类型错误11'), false)
        }
    }
}

  • 修改controller中的使用,功能和上面相同
    • 文件大小最大10M
    • 文件类型为图片image类型
import {
  Controller,
  Post,
  UploadedFile,
} from '@nestjs/common';
import {
  FileFilter,
  FiletypeFilter,
} from './file-filter/file-filter.decorator';

@Controller('file')
export class FileController {
  @Post('upload')
  @FileFilter('file', {
    limits: {
      fileSize: 1024 * 1024 * 10,
    },
    fileFilter: FiletypeFilter('image'),
  })
  fileUpload(@UploadedFile() file) {
    console.log('file', file);
    return {
      code: 200,
      file,
    };
  }
}

结尾

  • 好的,一个简单的nest文件上传到这就差不多了
  • 暂定下篇继续nest大文件分片上传的分享