NestJs uses upload function

To handle file uploads, NestJS provides a built-in module based on the multer middleware package. Multer handles data published in the multipart/form-data format, which is primarily used for file uploads via HTTP POST requests. The module is fully configurable and you can adjust its behavior according to your application requirements.

Note:
Multer cannot handle data in unsupported multipart formats (multipart/form-data). Also note that this package is not compatible with FastifyAdapter.

For better type safety, let's install the Multertypings package to take care of checking file types:

npm i -D @types/multer

basic example

To upload a single file, simply FileInterceptor()bind an interceptor to the route handler and use @UploadedFile()a decorator to extract the file from the request. Let's first implement a simple upload example. We just print out the uploaded file and take a look:

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

As you can see from the above example, FileInterceptor()the decorator has two parameters:

  • fileName: a string that provides the name of the field in the HTML form where the file is saved
  • options: Optional object of type MulterOptions. This is the same object used by the multer constructor. The options parameter usage of multer can be viewed here

Document verification

Often it is useful to validate incoming file metadata, such as file size or file MIME type. To do this, you can create your own Pipe and bind it to parameters annotated with the UploadedFile decorator. The following example demonstrates how to implement a basic file size validator pipeline:

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("上传文件超过指定大小");
    }
  }
}

If we use a custom pipeline, we can just add the pipeline to the corresponding route. The specific example is as follows:

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

In addition to being able to upload files using the above methods, NestJS also provides a built-in pipeline to handle common use cases and facilitate/standardize the addition of new use cases. The pipe is called ParseFilePipe and you can use it as follows:

@Post('/file')
uploadFileAndPassValidation(
  @UploadedFile(
    new ParseFilePipe({
    
    
      errorHttpStatusCode: 405,
      exceptionFactory: (error) => {
    
     return '文件上传失败' },
      validators: [
        // 此处的文件验证器实例集
      ]
    })
  )
  file: Express.Multer.File,
) {
    
    
  return {
    
    
    file: file.buffer.toString(),
  };
}

As can be seen from the above example, ParseFilePipethere are mainly three parameters, among which validatorsattributes are required, and errorHttpStatusCodeand exceptionFactoryare optional parameters. The description of these two optional parameters is as follows:

  • errorHttpStatusCode: HTTP status code thrown when any validator fails. Default is 400 (Bad Request)
  • exceptionFactory: a factory that receives error messages and returns errors

In NestJS, it consists of two built-in FileValidators, as detailed below:

  • MaxFileSizeValidator - Checks if the size of a given file is less than the provided value (measured in bytes)
  • FileTypeValidator - Checks if the mime type of a given file matches a given value

Specific examples of using the two built-in FileValidators in conjunction with the ParseFilePipe pipeline are as follows:

@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(),
  };
}

Finally, you can also use special ParseFilePipeBuilderclasses to compose and construct validators. By using it as shown below, you can avoid manually instantiating each validator and just pass their options directly:

@UploadedFile(
  new ParseFilePipeBuilder()
    .addFileTypeValidator({
    
    
      fileType: 'jpeg',
    })
    .addMaxSizeValidator({
    
    
      maxSize: 1000
    })
    .build({
    
    
      errorHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY
    }),
)
file: Express.Multer.File,

Through the above introduction, we already know how to verify uploaded files. In the above description, we used the built-in file verification class of NestJS. We can also write the file verification class ourselves. We only need to inherit the abstract class FileValidator. Can. Specific simple examples are as follows:

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.");
  }
}

Note:
To validate file types, the FileTypeValidator class uses the type detected by multer. By default, multer derives file types based on the file extension on the user's device. However, it does not check the actual file contents. Since files can be renamed to any extension, consider using a custom implementation if your application requires a more secure solution.

file array

To upload a file array, please use FilesInterceptor()the decorator. This decorator mainly has the following three parameters:

  • fieldName: A string that provides the field name in the HTML form where the file is saved. It is recommended to add an "s" after the name.
  • maxCount: optional number defining the maximum number of files accepted
  • options: Optional object of type MulterOptions. This is the same object used by the multer constructor. The options parameter usage of multer can be viewed here

Let's implement a request that limits the upload of 2 files. The specific code is as follows:

@Post('/files')
@UseInterceptors(FilesInterceptor('files', 2))
uploadFiles(@UploadedFiles() files: Array<Express.Multer.File>) {
    
    
  console.log(files)
  return {
    
    }
}

multiple files

To upload multiple files (all with different field name keys), use the FileFieldsInterceptor() decorator. This decorator takes two parameters:

  • uploadedFields: Array of objects, where each object specifies a required name attribute containing a string value specifying the field name and an optional maxCount attribute
  • options: Optional object of type MulterOptions. This is the same object used by the multer constructor. The options parameter usage of multer can be viewed here

Specific examples are as follows:

@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 {
    
    }
}

fileNameUnclear handling of uploads

Under normal circumstances, when we upload files, we will have a clear fileNamename, but sometimes business needs may cause fileNamethe name to be unclear, so we can use it AnyFilesInterceptor()to achieve such needs.

When using AnyFilesInterceptor(), use the @UploadedFiles() decorator to extract files from the request.

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

Default options

You can specify the multer option in the file interceptor as described above. To set default options, you can call the static register() method when importing the MulterModule, passing in the supported options. You can use all the options listed here.

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

Asynchronous configuration

Use the registerAsync() method when you need to set MulterModule options asynchronously rather than statically. Like most dynamic modules, Nest provides several techniques for handling asynchronous configuration.

One technique is to use factory functions:

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

Like other factory providers, our factory functions can be asynchronous and have dependencies injected via injection.

MulterModule.registerAsync({
    
    
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    
    
    dest: configService.get<string>("MULTER_DEST"),
  }),
  inject: [ConfigService],
});

Alternatively, you can configure the MulterModule using a class instead of a factory, as follows:

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

The above construct instantiates the MulterConfigService within the MulterModule and uses it to create the required options objects. Note that in this example, the MulterConfigService must implement the MulterOptionsFactory interface as shown below. MulterModule will call the createMulterOptions() method on the instantiated object of the provided class.

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

If you want to reuse an existing options provider instead of creating a private copy within the MulterModule, use useExisting syntax.

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

Guess you like

Origin blog.csdn.net/qq_33003143/article/details/132328011