## 文件上傳
為了處理文件上傳,Nest 提供了一個內置的基于 [multer](https://github.com/expressjs/multer) 中間件包的 Express 模塊。Multer 處理以 `multipart/form-data` 格式發送的數據,該格式主要用于通過 HTTP `POST` 請求上傳文件。這個模塊是完全可配置的,您可以根據您的應用程序需求調整它的行為。
> `Multer`無法處理不是受支持的多部分格式( `multipart/form-data` )的數據。 另外,請注意此程序包與 `FastifyAdapter` 不兼容。
為了更好的類型安全,我們來安裝 Multer 的類型聲明包:
```shell
$ npm i -D @types/multer
```
只要這個模塊被安裝,我們就可以使用 `Express.Multer.File` 這個類型(你可以通過 `import { Express } from 'express'` 導入這個類型)。
### 基本實例
當我們要上傳單個文件時, 我們只需將 `FileInterceptor()` 與處理程序綁定在一起, 然后使用 `@UploadedFile()` 裝飾器從 `request` 中取出 `file`。
```typescript
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
uploadFile(@UploadedFile() file: Express.Multer.File) {
console.log(file);
}
```
> `FileInterceptor()` 裝飾器是 `@nestjs/platform-express` 包提供的, `@UploadedFile()` 裝飾器是 `@nestjs/common` 包提供的。
`FileInterceptor()` 接收兩個參數:
- 一個 `fieldName` (指向包含文件的 HTML 表單的字段)
- 可選 `options` 對象, 類型為 `MulterOptions` 。這個和被傳入 multer 構造函數 ([此處](https://github.com/expressjs/multer#multeropts)有更多詳細信息) 的對象是同一個對象。
> `FileInterceptor()` 可能不兼容諸如 Google Firebase 之類的第三方云服務商。
### 文件數組
為了上傳文件數組,我們使用 `FilesInterceptor()`。請使用 `FilesInterceptor()` 裝飾器(注意裝飾器名稱中的復數文件)。這個裝飾器有三個參數:
- `fieldName`:(保持不變)
- `maxCount`:可選的數字,定義要接受的最大文件數
- `options`:可選的 `MulterOptions` 對象 ,如上所述
使用 `FilesInterceptor()` 時,使用 `@UploadedFiles()` 裝飾器從 `request` 中提取文件。
```typescript
@Post('upload')
@UseInterceptors(FilesInterceptor('files'))
uploadFile(@UploadedFiles() files: Array<Express.Multer.File>) {
console.log(files);
}
```
> `FilesInterceptor()` 裝飾器是 `@nestjs/platform-express` 包提供的, `@UploadedFiles()` 裝飾器是 `@nestjs/common` 包提供的。
### 多個文件
要上傳多個文件(全部使用不同的鍵),請使用 `FileFieldsInterceptor()` 裝飾器。這個裝飾器有兩個參數:
- `uploadedFields`:對象數組,其中每個對象指定一個必需的 `name` 屬性和一個指定字段名的字符串值(如上所述),以及一個可選的 `maxCount` 屬性(如上所述)
- `options`: 可選的 `MulterOptions` 對象,如上所述
使用 `FileFieldsInterceptor()` 時,使用 `@UploadedFiles()` 裝飾器從 `request` 中提取文件。
```typescript
@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);
}
```
### 任何文件
要使用任意字段名稱鍵上載所有字段,請使用 `AnyFilesInterceptor()` 裝飾器。該裝飾器可以接受如上所述的可選選項對象。
使用 `AnyFilesInterceptor()` 時,使用 `@UploadedFiles()` 裝飾器從 `request` 中提取文件。
```typescript
@Post('upload')
@UseInterceptors(AnyFilesInterceptor())
uploadFile(@UploadedFiles() files: Array<Express.Multer.File>) {
console.log(files);
}
```
### 默認選項
您可以像上面描述的那樣在文件攔截器中指定 `multer` 選項。要設置默認選項,可以在導入 `MulterModule` 時調用靜態 `register()` 方法,傳入受支持的選項。您可以使用[這里](https://github.com/expressjs/multer#multeropts)列出的所有選項。
```typescript
MulterModule.register({
dest: '/upload',
});
```
> `MulterModule` 類是 `@nestjs/platform-express` 包提供的。
### 異步配置
當需要異步而不是靜態地設置 `MulterModule` 選項時,請使用 `registerAsync()` 方法。與大多數動態模塊一樣,`Nest` 提供了一些處理異步配置的技術。
第一種可能的方法是使用工廠函數:
```typescript
MulterModule.registerAsync({
useFactory: () => ({
dest: '/upload',
}),
});
```
與其他[工廠提供程序](https://docs.nestjs.cn/8/fundamentals?id=%e5%b7%a5%e5%8e%82%e6%8f%90%e4%be%9b%e8%80%85-usefactory)一樣,我們的工廠函數可以是異步的,并且可以通過 `inject` 選項注入依賴。
```typescript
MulterModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
dest: configService.getString('MULTER_DEST'),
}),
inject: [ConfigService],
});
```
或者,您可以使用類而不是工廠來配置 `MulterModule`,如下所示:
```typescript
MulterModule.registerAsync({
useClass: MulterConfigService,
});
```
上面的構造在 `MulterModule` 中實例化 `MulterConfigService` ,使用它來創建所需的選項對象。注意,在本例中,`MulterConfigService` 必須實現 `MulterOptionsFactory` 接口,如下所示。`MulterModule` 將在提供的類的實例化對象上調用 `createMulterOptions()` 方法。
```typescript
@Injectable()
class MulterConfigService implements MulterOptionsFactory {
createMulterOptions(): MulterModuleOptions {
return {
dest: '/upload',
};
}
}
```
如果你想要重復使用一個已經存在的選項提供者而不是在 `MulterModule` 內創建一個私有的拷貝,使用 `useExisting` 語法。
```typescript
MulterModule.registerAsync({
imports: [ConfigModule],
useExisting: ConfigService,
});
```
### 例子
一個能夠運行的樣例[在這里](https://github.com/nestjs/nest/tree/master/sample/29-file-upload)。
- 介紹
- 概述
- 第一步
- 控制器
- 提供者
- 模塊
- 中間件
- 異常過濾器
- 管道
- 守衛
- 攔截器
- 自定義裝飾器
- 基礎知識
- 自定義提供者
- 異步提供者
- 動態模塊
- 注入作用域
- 循環依賴
- 模塊參考
- 懶加載模塊
- 應用上下文
- 生命周期事件
- 跨平臺
- 測試
- 技術
- 數據庫
- Mongo
- 配置
- 驗證
- 緩存
- 序列化
- 版本控制
- 定時任務
- 隊列
- 日志
- Cookies
- 事件
- 壓縮
- 文件上傳
- 流式處理文件
- HTTP模塊
- Session(會話)
- MVC
- 性能(Fastify)
- 服務器端事件發送
- 安全
- 認證(Authentication)
- 授權(Authorization)
- 加密和散列
- Helmet
- CORS(跨域請求)
- CSRF保護
- 限速
- GraphQL
- 快速開始
- 解析器(resolvers)
- 變更(Mutations)
- 訂閱(Subscriptions)
- 標量(Scalars)
- 指令(directives)
- 接口(Interfaces)
- 聯合類型
- 枚舉(Enums)
- 字段中間件
- 映射類型
- 插件
- 復雜性
- 擴展
- CLI插件
- 生成SDL
- 其他功能
- 聯合服務
- 遷移指南
- Websocket
- 網關
- 異常過濾器
- 管道
- 守衛
- 攔截器
- 適配器
- 微服務
- 概述
- Redis
- MQTT
- NATS
- RabbitMQ
- Kafka
- gRPC
- 自定義傳輸器
- 異常過濾器
- 管道
- 守衛
- 攔截器
- 獨立應用
- Cli
- 概述
- 工作空間
- 庫
- 用法
- 腳本
- Openapi
- 介紹
- 類型和參數
- 操作
- 安全
- 映射類型
- 裝飾器
- CLI插件
- 其他特性
- 遷移指南
- 秘籍
- CRUD 生成器
- 熱重載
- MikroORM
- TypeORM
- Mongoose
- 序列化
- 路由模塊
- Swagger
- 健康檢查
- CQRS
- 文檔
- Prisma
- 靜態服務
- Nest Commander
- 問答
- Serverless
- HTTP 適配器
- 全局路由前綴
- 混合應用
- HTTPS 和多服務器
- 請求生命周期
- 常見錯誤
- 實例
- 遷移指南
- 發現
- 誰在使用Nest?