12

I have a private aws s3 container full of images I want to use on my SPA. On the backend I am using express, to try to get access to these images. This is my code on node, where I get the object from s3 container, but I don't know how to display the image from the frontend, is there a way to do this? Do I have to make my s3 container public and use the URL, I was hoping to avoid this. Thanks

let express = require('express')
let router = express.Router();
const aws = require('aws-sdk');
require('dotenv').config();



    router.get('/', async (req,res) => {
    
        try{
            aws.config.setPromisesDependency(); //use so you can promisify to get the actual images
            aws.config.update({
                accessKeyId: process.env.ACCESSKEYID,
                secretAccessKey: process.env.SECRETACCESSKEY,
                region: 'us-east-1'
            });
    
            const s3 = new aws.S3();
             const list = await s3.listObjectsV2({
                Bucket: 'xxx-xxx-xxx'
            }).promise()
    
            res.send(list)
    
        } catch(e) {
            console.log('our error is',e)
        }
        
    
                
    })
    
    module.exports = router;

Could it be that I have to change the Content-Type? Since when I get the response from this, it's "application/json; charset=utf-8" when I read it in the chrome developer tool.

Jonathan G.
  • 243
  • 1
  • 2
  • 12

2 Answers2

5

You can keep the bucket private, all you need to use is the getSignedURLPromise() from the aws-SDK.

var params = {Bucket: 'xxx-xx-xxx', Key: '1.jpg'};
var promise = s3.getSignedUrlPromise('getObject', params);
promise.then(function(url) {
  res.send(url)
}, function(err) { console.log(err) });

This is literally all you need to get the URL that is safe to use, you can even put a time limit on how long its available for.

I found the answer here.

double-beep
  • 5,031
  • 17
  • 33
  • 41
Jonathan G.
  • 243
  • 1
  • 2
  • 12
  • 1
    Also if you want to get download/display multiple images, you can get listObjectsV2() and run a loop using the length. – Jonathan G. Oct 22 '20 at 03:52
  • Will this throw CORS error if it is signed URL ? – darth vader May 14 '21 at 23:28
  • I am trying to display image from a bucket on component and then on button click creating new canvas and attaching s3 object image to canvas and download whole canvas as png. – darth vader May 14 '21 at 23:30
0

What is your response from aws s3 looks like ? On the frontend you just have to call the api from your backend, and you will get the data as json. For example your response is like this

contents: [{
  'key': 'photo1',
  'url': 'www.xxxxxxx.com/photo1.png'
 }]

Then what you have to do is in the frontend part you have to set the src of your img tag by url that you will receive from backend.

<img src={url} />
Mahmud
  • 41
  • 3
  • maybe its because its listsObjectv2(), but I don't have a 'url' in my contents array when I get back my response. Do you think it's in listsObject() first version? – Jonathan G. Oct 22 '20 at 02:41
  • The URL you get from the response shouldn't be accessible by entering it in the browser or putting it in the image source. When making the bucket you should set permissions for IAM users and those permissions should be minimal, only letting app consumers do what is necessary(in most cases it's reading, uploading, and deleting files). By user, I mean application consumer(in his case express server). Allowing everyone to see any image is a security problem since you most likely don't want everyone to see your private data. So assigning URL to image source should return status 403(forbidden). – Andrija Gajic Nov 08 '21 at 16:01