1

I made a Node.js lambda service that's only capable of uploading .jpeg, .jpg, and .png. Using multer and express Right now the filtering is working and everything else too.

The problem I run into is that when the file is already uploaded, I cannot preview it from s3 console with the link s3 provides, instead it downloads the image directly.

Here's the code:

const fileFilter = (req, file, cb) => {
    let mimeType = file.mimetype;
    const fileString = file.originalname;
    let extension = path.extname(fileString);
    if(mimeType == 'image/jpeg'){
        if(extension == '.jpeg' || extension == '.jpg'){
            cb(null, true)
        } else {
            cb("File extension does not match the mimetype, check the file is not corrupt" + " " + extension + " and " + mimeType, false)
        }
    } else if( mimeType == 'image/png'){
        if(extension == '.png'){
            cb(null, true)
        } else {
            cb("File extension does not match the mimetype, check the file is not corrupt" + " " + extension + " and " + mimeType, false)
        }
    } else {
        cb("File type is not allowed" + " " + mimeType, false)
    }
}

const multerS3Config = multerS3({
    s3,
    acl: 'public-read',
    bucket: process.env.bucket,
    ContentType: multerS3.AUTO_CONTENT_TYPE,
    key: (req, file, cb) => {
        const fileString = file.originalname;
        const fileExtension = path.extname(fileString);
        let idSha256 = crypto.createHash('sha256').update(fileString).digest("hex");
        cb(null, `${idSha256}.${fileExtension}`);
    }
})

const upload = multer({
    storage: multerS3Config,
    fileFilter: fileFilter,
    limits:{
        fileSize: 1024 * 512
    }
}).single('photo')


service.post('/api/v1/images', (req, res) => {
    upload(req, res, (err) => {
        if (err) {
            res.status(400).send(err)
        } else {
            res.status(200).send('Success')
        }
    })
});

module.exports.service = serverless(service);

And here the serverless.yml

service: image-upload

frameworkVersion: '2'

custom:
  bucket: XXXXXXXXX
  default_stage: dev
  apigwBinary:
    types:
      - 'image/png'
      - 'image/jpeg'
      - 'image/jpg'



plugins:
  - serverless-apigw-binary
  - serverless-offline


provider:
  name: aws
  iamRoleStatements:
    - Effect: 'Allow'
      Action:
        - 's3:PutObject'
        - 's3:PutObjectAcl'
      Resource: 'XXXXXXX'
  runtime: nodejs12.x
  profile: image_uploader
  stage: ${opt:stage, self:custom.default_stage}

functions:
  uploadS3File:
    handler: handler.service
    environment:
      bucket: ${self:custom.bucket}-${self:provider.stage}
    events:
      - http:
          path: /api/v1/images
          method: post

For as I've been reading, it should work with the ContentType property on the multerS3 object, but so far, no luck.

Or Assayag
  • 5,662
  • 13
  • 57
  • 93

1 Answers1

0

if you opened the link on browser before adding the contentType in your code and try opening it again after adding the contentType in your code it will still download.

You have 2 options:-

  1. upload a new image and open the link in the browser

  2. open the same link in incognito

both of these solutions should work, i had the same problem and these 2 options worked perfectly.

kd12345
  • 689
  • 10
  • 29