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

NestJS Multer中间件上传后如何获取自定义新文件名?

问题分析与解决方案

首先,你的代码里有两个核心问题导致拿不到自定义的文件名:

  1. 中间件没有真正执行Multer的上传逻辑:你在resolve方法里只是创建了upload实例并调用了upload.any(),但这个方法返回的是一个中间件函数,你并没有用它去处理当前的req和res,所以你的自定义存储配置根本没生效,req.files还是原始的文件信息。

  2. Multer中间件与FilesInterceptor冲突:你同时使用了自定义的Multer中间件和NestJS提供的FilesInterceptor,这两者都是基于Multer实现的,拦截器会先于中间件处理请求,导致你的中间件配置被覆盖,自然拿不到你设置的文件名。

下面给你两种可行的解决方案:

方案一:直接在FilesInterceptor中配置存储(推荐)

既然你已经在使用NestJS的文件拦截器,完全可以把自定义的存储配置直接传到拦截器里,这样@UploadedFiles()装饰器就能拿到包含新文件名的文件对象:

// 先定义存储配置
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, path.join(__dirname, '../../uploads/'));
  },
  filename: (req, file, cb) => {
    const extArray = file.mimetype.split("/");
    const extension = extArray[extArray.length - 1];
    cb(null, `${file.fieldname}-${Date.now()}.${extension}`);
  }
});

// 在控制器中使用
@Post('upload')
@UseInterceptors(FilesInterceptor('files[]', 20, { storage }))
public async onUpload(@UploadedFiles() files) {
  // 这里的files里就包含你设置的新filename了
  console.log(files.map(file => file.filename));
  const mediaResponse = await this.media.saveMedias(0, files);
  return { status: true };
}

这种方式更符合NestJS的最佳实践,不需要额外的中间件。

方案二:修复自定义中间件并移除FilesInterceptor

如果你一定要用中间件来处理上传,需要修改中间件的逻辑,让它真正执行Multer的上传处理,同时控制器里不再使用FilesInterceptor:

修复后的中间件

@Injectable()
export class FilesMiddleware implements NestMiddleware {
  private storage = multer.diskStorage({
    destination: (req, file, cb) => {
      cb(null, path.join(__dirname, '../../uploads/'));
    },
    filename: (req, file, cb) => {
      const extArray = file.mimetype.split("/");
      const extension = extArray[extArray.length - 1];
      cb(null, `${file.fieldname}-${Date.now()}.${extension}`);
    }
  });

  resolve(...args: any[]): MiddlewareFunction {
    // 调用upload.any()返回中间件函数,并直接用它处理req、res、next
    const upload = multer({ storage: this.storage }).any();
    return upload;
  }
}

修改后的控制器

@Post('upload')
public async onUpload(@Request() req) {
  // 这里的req.files就是经过Multer处理后的文件对象,包含新filename
  console.log(req.files.map(file => file.filename));
  const mediaResponse = await this.media.saveMedias(0, req.files);
  return { status: true };
}

别忘了在模块里注册这个中间件:

@Module({
  // ...其他配置
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(FilesMiddleware)
      .forRoutes({ path: 'upload', method: RequestMethod.POST });
  }
}

这样修改后,你就能正确获取到自定义的文件名了。

内容的提问来源于stack exchange,提问作者Ben Beri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:29:32