Node js - Configuring aws s3 images on upload

28,688

Solution 1

This is the best source to answer my question, although I didn't originally find my answer here: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property

I found my answer here: http://blog.katworksgames.com/2014/01/26/nodejs-deploying-files-to-aws-s3/

You can simply add: ContentType: file.mimetype, ACL: 'public-read' to the params, turning:

var params = {Key: file.name, Body: ''};

into

var params = {Key: file.name, Body: '', ContentType: file.mimetype, ACL: 'public-read'};

EDIT:

Rather than supplying the file's mimetype, you could only allow particular mimetypes such as: 'image/jpg', 'image/jpeg', 'image/png', 'image/gif', etc...


EDIT #2: Original question is about configuring on upload, but this is also probably of relevance for some of the folks viewing this:

https://aws.amazon.com/premiumsupport/knowledge-center/s3-allow-certain-file-types/

Solution 2

I have added ContentType as below to fix this issue. For png or jpg, even without ContentType it will work. But if for uploading svg, you have to send ContentType property to S3 Bucket.

router.post(uploadImagePath, function (request, response) {
    var form = new formidable.IncomingForm();
    form.parse(request, (err, fields, files) => {
        try {
            let ImageName = files.file.name;
            fs.readFile(files.file.path, function (err, data) {
                let params = {
                    Bucket: 'Bucket-name',
                    Key: Date.now() + "_" + ImageName,
                    Body: data,
                    ACL: 'public-read',
                    ContentType: files.file.type
                };
                s3.upload(params, function (err, data) {
                    response.send(200, { key: data.key })
                });
            });
        }
        catch (e) {
            response.send(500);
        }
    })
});
Share:
28,688
heckascript
Author by

heckascript

HTML, CSS && SCSS/less JavaScript, Node.js && Deno // from ES5 => ES11 React, Vue, Ember && Angular // most to least recent UX && UI // a11y and i18n, workflows, visuals, motion SQL && graphQL Bash (Clojure lein) C# // Unity 3D python Ruby Rust C && C++ Docker && Kubernetes Puppet Self-taught Software Engineer who's tinkered with everything from embedded systems to machine learning, CLI's & services to API's & the frontend, and even native apps for macOS, windows, linux, iOS, and Android - but most often find myself dealing with distributed systems. Background in print and digital design.

Updated on November 18, 2020

Comments

  • heckascript
    heckascript over 3 years

    What's working so far:

    Using this function, I'm taking images that are uploaded to my server, sending them to an aws S3 bucket and then deleting them from my machine. That's all working great.

    The problem:

    How do I configure the image so that amazon serves it as public and with the proper Content-Type(image/jpeg or image/png)? Right now it defaults to private and (application/octet-stream).

    Is this something that I can configure in node? or do I need to do that in my aws console?

    function sendFileToAmazon(file) {
        var s3bucket = new AWS.S3({
          params: {Bucket: 'BUCKET NAME'}
        });
    
        var params = {Key: file.name, Body: ''};
    
        fs.readFile(file.path, function(err, data) {
          if (err) throw err;
          params.Body = data;
    
          s3bucket.putObject(params, function(errBucket, dataBucket) {
            if (errBucket) {
              console.log("Error uploading data: ", errBucket);
            } else {
              console.log(dataBucket);
              deleteFileFromTmp(file);
            }
          });
        });
      }
    
  • martinp999
    martinp999 about 7 years
    Be careful of the ContentType property! I was tearing my hair out until I noticed that I was using Content-Type as the property name.
  • corysimmons
    corysimmons over 6 years
    Wouldn't this solution allow for someone to upload any type of file? This doesn't restrict it to images as far as I can tell.
  • heckascript
    heckascript over 6 years
    Yeah I think you're right, looking back at this now... I'll update the ContentType
  • Gaurav Sharma
    Gaurav Sharma about 6 years
    This answer just saved me
  • Vitim.us
    Vitim.us over 5 years
    even tho it appears as a Metadata in a lot of places, it DOES NOT work if you PUT it as {"Key":key, "Body": body, "Metadata": {"Content-Type": "mime/type"} }
  • Zakher Masri
    Zakher Masri over 4 years
    In my case mimetype was in file.type