NestJS 文件上傳

2023-09-08 18:11 更新

為了處理文件上傳,Nest 提供了一個(gè)內(nèi)置的基于 multer 中間件包的 Express 模塊。Multer 處理以 multipart/form-data 格式發(fā)送的數(shù)據(jù),該格式主要用于通過(guò) HTTP POST 請(qǐng)求上傳文件。這個(gè)模塊是完全可配置的,您可以根據(jù)您的應(yīng)用程序需求調(diào)整它的行為。

Multer無(wú)法處理不是受支持的多部分格式( multipart/form-data )的數(shù)據(jù)。 另外,請(qǐng)注意此程序包與 FastifyAdapter 不兼容。

為了更好的類型安全,我們來(lái)安裝 Multer 的類型聲明包:

$ npm i -D @types/multer

只要這個(gè)模塊被安裝,我們就可以使用 Express.Multer.File 這個(gè)類型(你可以通過(guò) import { Express } from 'express' 導(dǎo)入這個(gè)類型)。

基本實(shí)例

當(dāng)我們要上傳單個(gè)文件時(shí), 我們只需將 FileInterceptor() 與處理程序綁定在一起, 然后使用 @UploadedFile() 裝飾器從 request 中取出 file。

@Post('upload')
@UseInterceptors(FileInterceptor('file'))
uploadFile(@UploadedFile() file: Express.Multer.File) {
  console.log(file);
}

FileInterceptor() 裝飾器是 @nestjs/platform-express 包提供的, @UploadedFile() 裝飾器是 @nestjs/common 包提供的。

FileInterceptor() 接收兩個(gè)參數(shù):

  • 一個(gè) fieldName (指向包含文件的 HTML 表單的字段)
  • 可選 options 對(duì)象, 類型為 MulterOptions 。這個(gè)和被傳入 multer 構(gòu)造函數(shù) (此處有更多詳細(xì)信息) 的對(duì)象是同一個(gè)對(duì)象。

FileInterceptor() 可能不兼容諸如 Google Firebase 之類的第三方云服務(wù)商。

文件數(shù)組

為了上傳文件數(shù)組,我們使用 FilesInterceptor()。請(qǐng)使用 FilesInterceptor() 裝飾器(注意裝飾器名稱中的復(fù)數(shù)文件)。這個(gè)裝飾器有三個(gè)參數(shù):

  • fieldName:(保持不變)
  • maxCount:可選的數(shù)字,定義要接受的最大文件數(shù)
  • options:可選的 MulterOptions 對(duì)象 ,如上所述

使用 FilesInterceptor() 時(shí),使用 @UploadedFiles() 裝飾器從 request 中提取文件。

@Post('upload')
@UseInterceptors(FilesInterceptor('files'))
uploadFile(@UploadedFiles() files: Array<Express.Multer.File>) {
  console.log(files);
}

FilesInterceptor() 裝飾器是 @nestjs/platform-express 包提供的, @UploadedFiles() 裝飾器是 @nestjs/common 包提供的。

多個(gè)文件

要上傳多個(gè)文件(全部使用不同的鍵),請(qǐng)使用 FileFieldsInterceptor() 裝飾器。這個(gè)裝飾器有兩個(gè)參數(shù):

  • uploadedFields:對(duì)象數(shù)組,其中每個(gè)對(duì)象指定一個(gè)必需的 name 屬性和一個(gè)指定字段名的字符串值(如上所述),以及一個(gè)可選的 maxCount 屬性(如上所述)
  • options: 可選的 MulterOptions 對(duì)象,如上所述

使用 FileFieldsInterceptor() 時(shí),使用 @UploadedFiles() 裝飾器從 request 中提取文件。

@Post('upload')
@UseInterceptors(FileFieldsInterceptor([
  { name: 'avatar', maxCount: 1 },
  { name: 'background', maxCount: 1 },
]))
uploadFile(@UploadedFiles() files: { avatar?: Express.Multer.File[], background?: Express.Multer.File[] }) {
  console.log(files);
}

任何文件

要使用任意字段名稱鍵上載所有字段,請(qǐng)使用 AnyFilesInterceptor() 裝飾器。該裝飾器可以接受如上所述的可選選項(xiàng)對(duì)象。

使用 AnyFilesInterceptor() 時(shí),使用 @UploadedFiles() 裝飾器從 request 中提取文件。

@Post('upload')
@UseInterceptors(AnyFilesInterceptor())
uploadFile(@UploadedFiles() files: Array<Express.Multer.File>) {
  console.log(files);
}

默認(rèn)選項(xiàng)

您可以像上面描述的那樣在文件攔截器中指定 multer 選項(xiàng)。要設(shè)置默認(rèn)選項(xiàng),可以在導(dǎo)入 MulterModule 時(shí)調(diào)用靜態(tài) register() 方法,傳入受支持的選項(xiàng)。您可以使用這里列出的所有選項(xiàng)。

MulterModule.register({
  dest: '/upload',
});

MulterModule 類是 @nestjs/platform-express 包提供的。

異步配置

當(dāng)需要異步而不是靜態(tài)地設(shè)置 MulterModule 選項(xiàng)時(shí),請(qǐng)使用 registerAsync() 方法。與大多數(shù)動(dòng)態(tài)模塊一樣,Nest 提供了一些處理異步配置的技術(shù)。

第一種可能的方法是使用工廠函數(shù):

MulterModule.registerAsync({
  useFactory: () => ({
    dest: '/upload',
  }),
});

與其他工廠提供程序一樣,我們的工廠函數(shù)可以是異步的,并且可以通過(guò) inject 選項(xiàng)注入依賴。

MulterModule.registerAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    dest: configService.getString('MULTER_DEST'),
  }),
  inject: [ConfigService],
});

或者,您可以使用類而不是工廠來(lái)配置 MulterModule,如下所示:

MulterModule.registerAsync({
  useClass: MulterConfigService,
});

上面的構(gòu)造在 MulterModule 中實(shí)例化 MulterConfigService ,使用它來(lái)創(chuàng)建所需的選項(xiàng)對(duì)象。注意,在本例中,MulterConfigService 必須實(shí)現(xiàn) MulterOptionsFactory 接口,如下所示。MulterModule 將在提供的類的實(shí)例化對(duì)象上調(diào)用 createMulterOptions() 方法。

@Injectable()
class MulterConfigService implements MulterOptionsFactory {
  createMulterOptions(): MulterModuleOptions {
    return {
      dest: '/upload',
    };
  }
}

如果你想要重復(fù)使用一個(gè)已經(jīng)存在的選項(xiàng)提供者而不是在 MulterModule 內(nèi)創(chuàng)建一個(gè)私有的拷貝,使用 useExisting 語(yǔ)法。

MulterModule.registerAsync({
  imports: [ConfigModule],
  useExisting: ConfigService,
});

例子

一個(gè)能夠運(yùn)行的樣例在這里。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)