fileTypeFromBuffer returns undefined

75 Views Asked by At

I´m building a serverless application focus in processing images in nestjs with serverless framework. I´m using multer to upload the images.

I have this code to validate the file:

    // required in order to use it in typescript
const { fileTypeFromBuffer } = await (eval(

      'import("file-type")',
    ) as Promise<typeof import('file-type')>);

    const fileType = await fileTypeFromBuffer(file.buffer);
    console.log('file', file);
    console.log('fileType', fileType);
    const allowedFileTypes = [
      'jpg',
      'jpeg',
      'png',
      'gif',
      'bmp',
      'webp',
      'svg',
    ];

Which generates the following output:

file {
  fieldname: 'file',
  originalname: 'mickey.png',
  encoding: '7bit',
  mimetype: 'image/png',
  buffer: <Buffer c2 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 7d 00 00 00 64 08 06 00 00 00 c2 ab 59 3f 76 00 00 00 01 73 52 47 42 00 c2 ae c3 8e 1c c3 ... 8075 more bytes>,
  size: 8125
}
fileType undefined // <--- THIS IS THE ERROR

The file seems to be ok, and it also have its mimetype, but when tryng to get the fileType from buffer I'm getting undefined.

The controller is:

@Post('upload/image')
  @UseInterceptors(FileInterceptor('file'))
  async uploadFile(
    @UploadedFile(
      new ParseFilePipe({
        validators: [
          new MaxFileSizeValidator({ maxSize: 16214400 }), //bytes = 25 MB
          new ImageTypeValidator({}), //{ fileType: 'image/jpeg' }
        ],
      }),
    )
    file: Express.Multer.File,
  ): Promise<FileDto> {
      return await this.fileCreateUseCase.exec(loggedUser, file, flow);
  }

Also, if I remove the validator, the app tries to process the image with Sharp, which generates an error that the fileType is not supported. So it seems that the buffer doesn't have a valid fileType.

I have exactly the same code in a regular project and the SAME images works fine. So no sure if it is something related to serverless or some configuration missing in multer or in the project.

This is the serverless.yml

service: serverless-example

plugins:
  - serverless-offline

provider:
  name: aws
  runtime: nodejs20.x
  memorySize: 1024
  ecr:
    images:
      api-image-name:
        path: ./
  apiGateway:
    binaryMediaTypes:
      - '*/*'
esbuild:
    # keep existing configurations
    external:
      - sharp
    packagerOptions:
      scripts:
        - npm install --platform=darwin --arch=arm64 sharp
functions:
  main:
    handler: dist/main.handler
    events:
      - http:
          method: ANY
          path: /
      - http:
          method: ANY
          path: '{proxy+}'
1

There are 1 best solutions below

4
Hai Alison On

I am not using file-type to check mimetype, but I check in the module file

    MulterModule.registerAsync({
      useFactory: () => ({
        storage: diskStorage({
          destination: (req, file, cb) => {
            return cb(null, resolve(process.env.INVOICE_PATH));
          },
          filename: (req: any, file: any, cb: any) => {
            cb(null, `${Date.now()}_${file.originalname}`);
          },
        }),
        fileFilter: (req, file, cb) => {                      //filter here
          if (!'application/pdf'.includes(file.mimetype)) {
            cb(
              new HttpException('file is not allowed', HttpStatus.BAD_REQUEST),
              false,
            );
          }
          cb(null, true);
        },
        limits: {
          fileSize: parseInt(process.env.MAX_SIZE_PER_FILE_UPLOAD),
          files: parseInt(process.env.MAX_NUMBER_FILE_UPLOAD),
        },
      }),
    }),