You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NestJS中同时使用platform-express与platform-fastify实现文件上传

解决方案:Fastify环境下实现NestJS文件上传

方案一:使用Fastify原生文件上传(推荐)

既然主应用基于Fastify,没必要硬套Express的multer,Fastify自身有成熟的文件上传支持,NestJS也提供了对应的适配工具。

步骤:

  1. 安装依赖
npm install @nestjs/platform-fastify fastify-multipart
  1. 在Fastify应用中注册文件上传插件
    在main.ts里初始化Fastify时,注册fastify-multipart:
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter()
  );
  // 注册fastify文件上传插件
  await app.register(require('fastify-multipart'));
  await app.listen(3000);
}
bootstrap();
  1. 使用NestJS提供的Fastify文件拦截器
    代替multer的FileInterceptor,使用FastifyFileInterceptor(来自@nestjs/platform-fastify):
import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FastifyFileInterceptor } from '@nestjs/platform-fastify';

@Controller('upload')
export class UploadController {
  @Post()
  @UseInterceptors(FastifyFileInterceptor('file'))
  async uploadFile(@UploadedFile() file: any) {
    // 处理文件逻辑,比如保存到磁盘、验证文件类型/大小
    return {
      filename: file.filename,
      size: file.size,
      mimetype: file.mimetype
    };
  }
}
  1. 文件验证
    可以结合class-validator和自定义管道实现验证,比如检查文件大小、类型:
import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';

@Injectable()
export class FileValidationPipe implements PipeTransform {
  transform(file: any) {
    const maxSize = 1024 * 1024; // 1MB
    const allowedTypes = ['image/jpeg', 'image/png'];
    
    if (file.size > maxSize) {
      throw new BadRequestException('文件大小不能超过1MB');
    }
    if (!allowedTypes.includes(file.mimetype)) {
      throw new BadRequestException('仅支持JPG/PNG格式');
    }
    return file;
  }
}

在路由中使用:

@Post()
@UseInterceptors(FastifyFileInterceptor('file'))
async uploadFile(@UploadedFile(FileValidationPipe) file: any) {
  // 处理文件
}

方案二:为特定路由挂载Express子应用(仅当必须用multer时)

如果你的业务逻辑严重依赖multer的现有代码,不想重写,可以创建一个独立的Express子应用,挂载到主Fastify应用的特定路由前缀下。

步骤:

  1. 安装Express相关依赖
npm install @nestjs/platform-express multer @types/multer
  1. 创建Express子应用并挂载
    在main.ts中,同时初始化Fastify主应用和Express子应用,将子应用挂载到/upload路径:
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { ExpressAdapter } from '@nestjs/platform-express';
import { AppModule } from './app.module';
import { UploadModule } from './upload/upload.module'; // 你的上传模块

async function bootstrap() {
  // 初始化Fastify主应用
  const fastifyApp = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter()
  );

  // 初始化Express子应用,处理上传路由
  const expressApp = await NestFactory.create(
    UploadModule,
    new ExpressAdapter()
  );

  // 将Express子应用挂载到Fastify的/upload路径
  fastifyApp.use('/upload', expressApp.getHttpAdapter().getInstance());

  await fastifyApp.listen(3000);
}
bootstrap();
  1. 在Express子应用的模块中使用multer
    在UploadModule对应的控制器中,正常使用multer的拦截器:
import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname } from 'path';

@Controller()
export class UploadController {
  @Post()
  @UseInterceptors(FileInterceptor('file', {
    storage: diskStorage({
      destination: './uploads',
      filename: (req, file, cb) => {
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
        cb(null, file.fieldname + '-' + uniqueSuffix + extname(file.originalname));
      }
    }),
    limits: { fileSize: 1024 * 1024 },
    fileFilter: (req, file, cb) => {
      if (!file.originalname.match(/\.(jpg|png)$/)) {
        return cb(new Error('仅支持JPG/PNG文件'), false);
      }
      cb(null, true);
    }
  }))
  async uploadFile(@UploadedFile() file: Express.Multer.File) {
    return { filename: file.filename };
  }
}

方案对比

  • 方案一:完全贴合Fastify生态,性能更优,避免双引擎的额外开销,是官方推荐的做法。
  • 方案二:适合已有大量multer相关代码的场景,但会引入Express引擎的额外依赖,增加系统复杂度。

内容的提问来源于stack exchange,提问作者Даня Сингл

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 09:18:13