ファイルのアップロードを処理するために、NestJS は multer ミドルウェア パッケージに基づく組み込みモジュールを提供します。Multer は、multipart/form-data 形式で公開されたデータを処理します。これは主に HTTP POST リクエストを介したファイルのアップロードに使用されます。このモジュールは完全に構成可能であり、アプリケーションの要件に応じて動作を調整できます。
注:
Multer は、サポートされていないマルチパート形式 (multipart/form-data) のデータを処理できません。また、このパッケージは FastifyAdapter と互換性がないことに注意してください。
タイプセーフを向上させるために、ファイルタイプのチェックを行う Multertypings パッケージをインストールしましょう。
npm i -D @types/multer
基本的な例
単一のファイルをアップロードするには、単純にFileInterceptor()
インターセプターをルート ハンドラーにバインドし、@UploadedFile()
デコレーターを使用してリクエストからファイルを抽出します。まず簡単なアップロードの例を実装しましょう。アップロードされたファイルを印刷して見てみましょう。
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
uploadFile(@UploadedFile() file: Express.Multer.File) {
console.log(file);
}
上の例からわかるように、FileInterceptor()
デコレーターには 2 つのパラメーターがあります。
- fileName: ファイルが保存される HTML フォーム内のフィールドの名前を提供する文字列
- options: MulterOptions タイプのオプションのオブジェクト。これは、multer コンストラクターで使用されるオブジェクトと同じです。multer のオプション パラメーターの使用法はここで確認できます。
書類確認
多くの場合、ファイル サイズやファイル MIME タイプなど、受信ファイルのメタデータを検証すると便利です。これを行うには、独自のパイプを作成し、それを、UploadedFile デコレータで注釈が付けられたパラメータにバインドします。次の例は、基本的なファイル サイズ検証パイプラインを実装する方法を示しています。
import {
PipeTransform,
Injectable,
ArgumentMetadata,
BadRequestException,
} from "@nestjs/common";
@Injectable()
export class FileSizeValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
const oneKb = 1000;
if (value.size < oneKb) {
return true;
} else {
throw new BadRequestException("上传文件超过指定大小");
}
}
}
カスタム パイプラインを使用する場合は、対応するルートにパイプラインを追加するだけで済みます。具体的な例は次のとおりです。
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
@UsePipes(new FileSizeValidationPipe())
uploadFile(@UploadedFile() file: Express.Multer.File) {
console.log(file);
}
上記のメソッドを使用してファイルをアップロードできることに加えて、NestJS は、一般的なユース ケースを処理し、新しいユース ケースの追加を容易/標準化するための組み込みパイプラインも提供します。このパイプは ParseFilePipe と呼ばれ、次のように使用できます。
@Post('/file')
uploadFileAndPassValidation(
@UploadedFile(
new ParseFilePipe({
errorHttpStatusCode: 405,
exceptionFactory: (error) => {
return '文件上传失败' },
validators: [
// 此处的文件验证器实例集
]
})
)
file: Express.Multer.File,
) {
return {
file: file.buffer.toString(),
};
}
上記の例からわかるように、ParseFilePipe
主に 3 つのパラメータがあり、そのうちのvalidators
属性は必須であり、 とerrorHttpStatusCode
はexceptionFactory
オプションのパラメータです。これら 2 つのオプションのパラメーターの説明は次のとおりです。
- errorHttpStatusCode: バリデーターが失敗したときにスローされる HTTP ステータス コード。デフォルトは 400 (不正なリクエスト)
- ExceptionFactory: エラーメッセージを受信してエラーを返すファクトリ
NestJS では、以下に詳しく説明するように、2 つの組み込み FileValidator で構成されます。
- MaxFileSizeValidator - 指定されたファイルのサイズが指定された値 (バイト単位で測定) より小さいかどうかを確認します。
- FileTypeValidator - 指定されたファイルの MIME タイプが指定された値と一致するかどうかを確認します
2 つの組み込み FileValidator を ParseFilePipe パイプラインと組み合わせて使用する具体的な例は次のとおりです。
@Post('/file')
uploadFileAndPassValidation(
@UploadedFile(
new ParseFilePipe({
errorHttpStatusCode: 405,
exceptionFactory: (error) => {
return '文件上传失败' },
validators: [
new MaxFileSizeValidator({
maxSize: 1000 }),
new FileTypeValidator({
fileType: 'image/jpeg' }),
]
})
)
file: Express.Multer.File,
) {
return {
file: file.buffer.toString(),
};
}
最後に、特別なParseFilePipeBuilder
クラスを使用してバリデータを構成および構築することもできます。以下に示すようにこれを使用すると、各バリデーターを手動でインスタンス化することを回避し、オプションを直接渡すだけです。
@UploadedFile(
new ParseFilePipeBuilder()
.addFileTypeValidator({
fileType: 'jpeg',
})
.addMaxSizeValidator({
maxSize: 1000
})
.build({
errorHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY
}),
)
file: Express.Multer.File,
上記の紹介で、アップロードされたファイルを検証する方法はすでにわかりました。上記の説明では、NestJS の組み込みファイル検証クラスを使用しました。ファイル検証クラスを自分で記述することもできます。抽象クラスを継承するだけで済みますFileValidator
。できる。具体的な簡単な例は次のとおりです。
import {
FileValidator } from "@nestjs/common";
export class CustomFileValidatot extends FileValidator {
isValid(file?: any): boolean | Promise<boolean> {
throw new Error("Method not implemented.");
}
buildErrorMessage(file: any): string {
throw new Error("Method not implemented.");
}
}
注:
ファイル タイプを検証するために、FileTypeValidator クラスは multer によって検出されたタイプを使用します。デフォルトでは、multer はユーザーのデバイス上のファイル拡張子に基づいてファイルタイプを派生します。ただし、実際のファイルの内容はチェックされません。ファイル名は任意の拡張子に変更できるため、アプリケーションでより安全なソリューションが必要な場合は、カスタム実装の使用を検討してください。
ファイル配列
ファイル配列をアップロードするには、FilesInterceptor()
デコレータを使用してください。このデコレータには主に次の 3 つのパラメータがあります。
- fieldName: ファイルが保存される HTML フォーム内のフィールド名を指定する文字列。名前の後に「s」を追加することをお勧めします。
- maxCount: 受け入れられるファイルの最大数を定義するオプションの数値
- options: MulterOptions タイプのオプションのオブジェクト。これは、multer コンストラクターで使用されるオブジェクトと同じです。multer のオプション パラメーターの使用法はここで確認できます。
2 つのファイルのアップロードを制限するリクエストを実装してみましょう。具体的なコードは次のとおりです。
@Post('/files')
@UseInterceptors(FilesInterceptor('files', 2))
uploadFiles(@UploadedFiles() files: Array<Express.Multer.File>) {
console.log(files)
return {
}
}
複数のファイル
複数のファイル (すべて異なるフィールド名キーを持つファイル) をアップロードするには、FileFieldsInterceptor() デコレーターを使用します。このデコレータは 2 つのパラメータを取ります。
- uploadedFields: オブジェクトの配列。各オブジェクトは、フィールド名を指定する文字列値とオプションの maxCount 属性を含む必須の name 属性を指定します。
- options: MulterOptions タイプのオプションのオブジェクト。これは、multer コンストラクターで使用されるオブジェクトと同じです。multer のオプション パラメーターの使用法はここで確認できます。
具体的な例としては以下のようなものがあります。
@Post('/files')
@UseInterceptors(FileFieldsInterceptor([
{
name: 'files', maxCount: 1 },
{
name: 'excels', maxCount: 1 },
]))
uploadFiles(@UploadedFiles() files: {
files?: Express.Multer.File[], excels?: Express.Multer.File[] }) {
console.log(files)
return {
}
}
アップロードfileName
の扱いが不明確
通常の状況では、ファイルをアップロードするときは明確な名前が付けられますfileName
が、ビジネス ニーズによって名前が不明瞭になる場合があるため、そのようなニーズを実現するためにfileName
使用できます。AnyFilesInterceptor()
AnyFilesInterceptor() を使用する場合は、 @UploadedFiles() デコレータを使用してリクエストからファイルを抽出します。
@Post('upload')
@UseInterceptors(AnyFilesInterceptor())
uploadFile(@UploadedFiles() files: Array<Express.Multer.File>) {
console.log(files);
}
デフォルトのオプション
上で説明したように、ファイル インターセプターで multer オプションを指定できます。デフォルトのオプションを設定するには、MulterModule をインポートするときに静的 register() メソッドを呼び出し、サポートされているオプションを渡します。ここにリストされているすべてのオプションを使用できます。
MulterModule.register({
dest: "./upload",
});
非同期構成
MulterModule オプションを静的ではなく非同期的に設定する必要がある場合は、 registerAsync() メソッドを使用します。ほとんどの動的モジュールと同様に、Nest は非同期構成を処理するためのいくつかの手法を提供します。
1 つの手法は、ファクトリー関数を使用することです。
MulterModule.registerAsync({
useFactory: () => ({
dest: "./upload",
}),
});
他のファクトリ プロバイダーと同様に、ファクトリ関数は非同期にすることができ、インジェクションによって依存関係を注入することができます。
MulterModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
dest: configService.get<string>("MULTER_DEST"),
}),
inject: [ConfigService],
});
あるいは、次のように、ファクトリの代わりにクラスを使用して MulterModule を構成することもできます。
MulterModule.registerAsync({
useClass: MulterConfigService,
});
上記の構造は、MulterModule 内で MulterConfigService をインスタンス化し、それを使用して必要なオプション オブジェクトを作成します。この例では、MulterConfigService は次に示すように MulterOptionsFactory インターフェイスを実装する必要があることに注意してください。MulterModule は、提供されたクラスのインスタンス化されたオブジェクトに対して createMulterOptions() メソッドを呼び出します。
@Injectable()
class MulterConfigService implements MulterOptionsFactory {
createMulterOptions(): MulterModuleOptions {
return {
dest: "./upload",
};
}
}
MulterModule 内にプライベート コピーを作成するのではなく、既存のオプション プロバイダーを再利用する場合は、useExisting 構文を使用します。
MulterModule.registerAsync({
imports: [ConfigModule],
useExisting: ConfigService,
});