Nodejs upload images to amazon s3

2 months ago

Lets implement how to upload images to s3.

We follow this tut with a bit of change

https://www.terlici.com/2015/05/23/uploading-files-S3.html

The change

before
url: 'https://s3.amazonaws.com/'
after
url: 'https://s3-ap-southeast-1.amazonaws.com/'

Bucket Configuration

S3 stores your data in buckets. Let’s create a specific bucket for this task and name it ‘thietke102’. Click it

Then select the ‘Properties’ tab in your bucket. Click on “Permissions” and then “Add CORS Configuration” and use the following configuration.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

It configures your bucket to allow the usual HTTP requests sent from any computer. However, each request still needs to be authenticated or it will fail.

Now that your bucket is ready, you are ready to write some code.

server.js

var express = require('express');
var aws = require('aws-sdk');
var app = express();

  app.get('/', function(req, res) {
   res.sendFile(__dirname + '/index.html');
  })

  var AWS_ACCESS_KEY = '?'
  var AWS_SECRET_KEY = '?'
  var S3_BUCKET = 'thietke102'

  app.get('/sign', function(req, res) {
    aws.config.update({accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY});

    var s3 = new aws.S3()
    var options = {
      Bucket: S3_BUCKET,
      Key: req.query.file_name,
      ContentType: req.query.file_type,
      ACL: 'public-read'
    }

    s3.getSignedUrl('putObject', options, function(err, data){
      if(err) return res.send('Error with S3')

      	// if success do some thing
      // img url
      var img_url ='https://s3-ap-southeast-1.amazonaws.com/' + S3_BUCKET + '/' + req.query.file_name;


      	console.log(img_url);
      	// insert to database.... 

      res.json({
        signed_request: data,
        url: img_url

      })
    })
  })
app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

Index

<!DOCTYPE html>
<html>
  <head>
    <title>Limitless Image Upload</title>
  </head>
  <body>
    <h1>Welcome!</h1>
    <br>Please select an image
    <input type="file" id="image">
    <br>
    <img id="preview">


    
  </body>
</html>

Javascript (can use direct in index.html)


    function upload(file, signed_request, url, done) {
      var xhr = new XMLHttpRequest()
      xhr.open("PUT", signed_request)
      xhr.setRequestHeader('x-amz-acl', 'public-read')
      xhr.onload = function() {
        if (xhr.status === 200) {
          done()
        }
      }

      xhr.send(file)
    }

    function sign_request(file, done) {
      var xhr = new XMLHttpRequest()
      xhr.open("GET", "/sign?file_name=" + file.name + "&file_type=" + file.type)

      xhr.onreadystatechange = function() {
        if(xhr.readyState === 4 && xhr.status === 200) {
          var response = JSON.parse(xhr.responseText)
          done(response)
        }
      }

      xhr.send()
    }

    document.getElementById("image").onchange = function() {
      var file = document.getElementById("image").files[0]
      if (!file) return

      sign_request(file, function(response) {
        upload(file, response.signed_request, response.url, function() {
          document.getElementById("preview").src = response.url
        })
      })
    }
  

It’s quite a lot of code but don’t worry, it is very simple.

First at the beginning of the page we have a simple file field which the user can use to choose a file.

The more interesting part is in the JavaScript section at the bottom of the page. First, we listen to the change event of the file field with onchange which is fired when the user selects a file.

When fired we use the sign_request function to get a signed temporary URL where the browser can upload the file. Then again using AJAX you upload the file with the uploadfunction to the temporary URL.

Once the file is uploaded we display it to the user.

This is everything that you have to do. As you can see the file never reaches your server. Only tiny little bit of data is actually handle by it. Almost the entire workload is handled by S3.

Don’t forget, S3 is great not only for uploading and storing files, but it is also very capable of serving files. It can easily server files of all sizes to millions of users simultaneously.

REference

https://aws.amazon.com/sdk-for-node-js/