a blog for those who code

Sunday, 3 March 2019

Upload Images to Digital Ocean Spaces using React

In this post we will be discussing about uploading images to Digital Ocean Spaces using React.js. Digital Ocean Spaces allows you to store and vast amount of contents be it images, video or audio. It's S3 compatible object storage which has built in CDN that makes scaling easy, reliable and affordable. The pricing starts from $5 in which you will get 250 GB of storage, 1 TB of outbound transfer and unlimited uploads.

We will be using DO Spaces API, which provides RESTful XML API for pro-grammatically managing the data. The API is inter-operable with Amazon's AWS S3 API that means it allows you to interact with the service while using the tools you already know.

Prerequistes


To work with this tutorial you need to have a DigitalOcean Space, along with an access key and secret key to your account. Learn here how to set up the Digital Ocean Space along with access key and secret key. Also you need to install aws-sdk in you application using npm : npm install --save aws-sdk


Code


At first we will be creating a file named DigitalOcean.js and add the following code to it

import AWS from 'aws-sdk';

/**
 * Digital Ocean Spaces Connection
 */

const spacesEndpoint = new AWS.Endpoint('nyc3.digitaloceanspaces.com');
const s3 = new AWS.S3({
      endpoint: spacesEndpoint,
      accessKeyId: process.env.ACCESS_KEY_ID,
      secretAccessKey: process.env.ACCESS_SECRET_KEY
    });
export default s3;


In the above code we are connecting to the DigitalOcean Spaces API. At first you need to see which region your spaces is located and the spacesEndPoint will point to that location, in our case it is nyc3. You need to add the ACCESS_KEY_ID and ACCESS_SECRET_KEY in the environment variable.

We will also be creating a config.js file which will have the bucket name and DO Spaces full url as shown below :

export default {
  digitalOceanSpaces: 'https://myBucketName.nyc3.digitaloceanspaces.com/',
  bucketName: 'myBucketName'
};

On the front-end we will be adding a input tag of type file which will always accept an image type as shown below :

<input type="file" id="inputfile" accept="image/*"
            onChange={this.handleImageChange} />

Then we will have a prop which will send the data to the Digital Ocean Spaces using the S3.putObject function as shown below :

handleImageChange = (e) => {
  if (e.target.files && e.target.files[0]) {
    blob = e.target.files[0];
    const params = { Body: blob, 
                     Bucket: `${Config.bucketName}`, 
                     Key: blob.name};
     // Sending the file to the Spaces
     S3.putObject(params)
       .on('build', request => {
         request.httpRequest.headers.Host = `${Config.digitalOceanSpaces}`;
         request.httpRequest.headers['Content-Length'] = blob.size;
         request.httpRequest.headers['Content-Type'] = blob.type;
         request.httpRequest.headers['x-amz-acl'] = 'public-read';
      })
      .send((err) => {
        if (err) errorCallback();
        else {
        // If there is no error updating the editor with the imageUrl
        const imageUrl = `${Config.digitalOceanSpaces}` + blob.name
        callback(imageUrl, blob.name)
       }
    });
  }
};

Do note that x-amz-acl is only needed if you want to allow the public to have an access to your images otherwise you can remove that line.

No comments:

Post a Comment