nest.js 上传文件示例

222 阅读1分钟

问题

  • nest官方上传示文件示例不完美,虽然能运行,但是代码提示有错误。
    • 错误1:Namespace 'global.Express' has no exported member 'Multer'
    • 错误2:Argument type Type is not assignable to parameter type NestInterceptor | FunctionNestInterceptor

解决

  • package
    • npm i -D @types/multer
    • npm i @nestjs/platform-express
"dependencies": {
  "@nestjs/common": "^10.0.0",
  "@nestjs/config": "^3.2.3",
  "@nestjs/core": "^10.0.0",
  "@nestjs/platform-express": "^10.4.4",
  "@nestjs/schedule": "^4.1.1",
  "@nestjs/serve-static": "^4.0.2",
  "class-transformer": "^0.5.1",
  "class-validator": "^0.14.1",
  "ioredis": "^5.4.1",
  "mysql2": "^3.11.3"
},
"devDependencies": {
  "@nestjs/cli": "^10.0.0",
  "@nestjs/schematics": "^10.0.0",
  "@nestjs/testing": "^10.0.0",
  "@types/busboy": "^1.5.4",
  "@types/jest": "^29.5.2",
  "@types/lodash": "^4.17.10",
  "@types/multer": "^1.4.12",
  "@types/node": "^20.3.1",
  "@types/supertest": "^6.0.0",
  "@typescript-eslint/eslint-plugin": "^8.0.0",
  "@typescript-eslint/parser": "^8.0.0",
  "eslint": "^8.42.0",
  "eslint-config-prettier": "^9.0.0",
  "eslint-plugin-prettier": "^5.0.0",
  "jest": "^29.5.0",
  "prettier": "^3.0.0",
  "source-map-support": "^0.5.21",
  "supertest": "^7.0.0",
  "ts-jest": "^29.1.0",
  "ts-loader": "^9.4.3",
  "ts-node": "^10.9.1",
  "tsconfig-paths": "^4.2.0",
  "typescript": "^5.1.3"
},
  • 控制器
import { Controller, Post, Inject, UseInterceptors, UploadedFile, Req } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import 'multer';
import * as helper from '../../helper';

@Controller('cat')
export class CatController {
    
  @Post('upload')
  @UseInterceptors(new (FileInterceptor('file')))
  uploadFile(
    @UploadedFile() file: Express.Multer.File
  ) {
    return helper.msg('ok', file);
  }
}

直接调用busboy库方案

  • 如果想要更加自由的上传文件,可以不用官方示例。
  • package
    • npm i -D @types/busboy
  • controller
import { Controller, Post, Inject, UseInterceptors, UploadedFile, Req } from '@nestjs/common';
import * as busboy from 'busboy';
import * as fs from 'node:fs';
import * as path from 'node:path';
import * as helper from '../../helper';

    
async function up(req, fileName = '') {
  return new Promise((resolve, reject)=>{
    let saveTo;
    const bb = busboy({ headers: req.headers });
    bb.on('file', (name, file, info) => {
      // const saveTo = path.join(os.tmpdir(), `busboy-upload-${random()}`);
      saveTo = path.resolve('./upload/' + (fileName || Math.random()));
      file.pipe(fs.createWriteStream(saveTo));
      resolve({name, file, info});
    });
    bb.on('close', () => {
      resolve('close');
    });
    req.pipe(bb);
  });

}

@Controller('cat')
export class CatController {
    
    @Post('upload')
    async uploadFile(
      @Req() request: any,
    ) {
      const res = await up(request);
      return helper.msg('ok', res);
    }
}