Home > other >  downloading image file from AWS S3 bucket using nodejs, UPDATE :12/12
downloading image file from AWS S3 bucket using nodejs, UPDATE :12/12

Time:12-15

I want to store images in an S3 bucket and then download the images via an http request using AWS's SDK for nodejs.

Here's my set up

// aws.js
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');

const config = ({
  region:  'us-east-2',
  credentials: {
    accessKeyId: "ACCESS_KEY",
    secretAccessKey: "SECRET_ACCESS_KEY"
  }
})

const s3Client = new S3Client(config);

const bucketParams = {
  Bucket: 'aws-bucket',
  Key: 'image1.jpg'
}

const getS3 = async () => {
  try {
    const data = await s3Client.send(new GetObjectCommand(bucketParams));
    return await data.Body.transformToString();
  } catch (err) {
    console.log('err:', err);
  }
}

getS3()
  .then((res) => {
    console.log('res:', res)
  })
  .catch((err) => {
    console.log('err:', err);
  });

When I send the request I expect to see a url, or a url in an object printed to the console like this:

res: "https://test-bucket-from-nodejs-sdk.s3.us-east-2.amazonaws.com/image1.jpg"

// or

res: ["https://test-bucket-from-nodejs-sdk.s3.us-east-2.amazonaws.com/image1.jpg"]

This is what gets printed to the console

res: �����%��~       Z�����o�~����!������8~�_�O|&��.��=wG��M�f�'C6Ww3�1��H�t�l(f�{)�G�0���~Ο���?�[�'���;�t��|=��F�Ƌ&��ƭ$�鬓Γyq)���� �@?d���F����amw᎗����W���\����4�:��PI��¤W��_�H��O*        %�F���Dg���%�oŽw�m��u�{=N��(|I=�CCԗP�q
           ۸�J ���
���A҆��$���q�sx��L8K�\*�cߊ���O��6�.��_
s���������w���?���|W�S��.�R49 �S���%�o��4�O<]&7Eq�N���~��_�ટ�����|n�|k������ׅ�/�>�
N<2�   �9H@�x���N�
Y�x3X�{��K��y<]�B�_��<7���I����1Ln��I-�E��K
                                           ��
*[���dN�SE|����^��|5⋋/k>
��mWP�u(`��c5��մ�K�R�q
                      �����w~ֿ
                             >"��⯀�[��_5(�|C��¢�� }F�YU�g����r�)U�B� OQ_���U|u�|S�Ś?�t�M:�U���O.-[Q��P���nKFm�۱,�b��]dT�<-�9��|W�v��徛��L|y�|5մ
                                                                   �8����Zƥk�Em�[��4X���i$�Y���K�

I think it's because image files aren't readable in a node server environment, which might explain the replacement chars.

Does that I mean I need some kind of middleware like a buffer to make the image file readable?

  • UPDATE

I've resolved half the problem... I was using the wrong S3Client method. What I should've been using was ListObjectsV2Command instead of GetObjectCommand.

updated code:

///aws.js
const { S3Client, ListObjectsV2Command } = require('@aws-sdk/client-s3');

const s3Client = new S3Client(config);

const getS3List = async () => {
  const command = new ListObjectsV2Command({Bucket:'test-bucket-from-nodejs-sdk'});
  const response = await s3Client.send(command);
  return response;
}

getS3List()
  .then((data) => {
    console.log('data:', data);
  })

This returns a json object with a list of the object keys in the s3 bucket

// bash window
node aws.js 
data: {
  '$metadata': {
    httpStatusCode: 200,
    requestId: 'FH5WZY9VXGGQ5BWC',
    extendedRequestId: 'pCMCEpPggwNka9Sj/jWZpFo8HmT/j2gd2B93i/COf8v3clgBWfK1Zw5tK3jbChOEuqKd756vRes=',
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  },
  Contents: [
    {
      Key: 'helloWorld.txt',
      LastModified: 2022-12-12T01:13:23.000Z,
      ETag: '"5eb63bbbe01eeed093cb22bb8f5acdc3"',
      ChecksumAlgorithm: undefined,
      Size: 11,
      StorageClass: 'STANDARD',
      Owner: undefined
    },
    {
      Key: 'image1.jpg',
      LastModified: 2022-12-12T01:09:41.000Z,
      ETag: '"8b82adec06401f845e9564b05d3908dd"',
      ChecksumAlgorithm: undefined,
      Size: 192757,
      StorageClass: 'STANDARD',
      Owner: undefined
    }
  ],
  IsTruncated: false,
  KeyCount: 2,
  MaxKeys: 1000,
  Name: 'test-bucket-from-nodejs-sdk',
  Prefix: ''
}

NOW the issue is making a working url to map over an image tag using the Keys, I've tried using the Object URL and s3 URI addresses as src attributes and neither one work.

// server.js
app.get('/test', (req, res) => {
  getS3List()
    .then((data) => {
      console.log(data.Contents[1].Key)
      res.send(`<img src='https://test-bucket-from-nodejs-sdk.s3.us-east-2.amazonaws.com/${data.Contents[1].Key}'/>`)
    })
    .catch((err) => {
      throw err;
    })
})

Any thoughts?

I'm expecting the S3 server to return the url of the image stored in the bucket that I can use as the src for an html tag. The when I call the /test endpoint I want the tag with the s3 image url used a a source to be returned and rendered on the browser window

ex: expected behavior

// app.js
app.get('/test', (req, res) => {
  getS3List()
    .then((data) => {
      console.log(data.Contents[1].Key)
      res.send(`<img src=${'https://res.cloudinary.com/darp0mj9i/image/upload/v1670551774/fabio/theater/Dario_Fo_s_theatrical_show_G._Polidori_designer_uwv3mf.jpg'}></img>`)
    })
    .catch((err) => {
      throw err;
    })
})

renders this

enter image description here

But this is what ends up happending when I use the s3 object url

app.get('/test', (req, res) => {
  getS3List()
    .then((data) => {
      console.log(data.Contents[1].Key)
      res.send(`<img src='https://test-bucket-from-nodejs-sdk.s3.us-east-2.amazonaws.com/${data.Contents[1].Key}'></img>`)
    })
    .catch((err) => {
      throw err;
    })
})

enter image description here

Which means it's not a valid url

CodePudding user response:

In order to get access to an object's url stored in an AWS S3 bucket, you either need to enable public read access or create a pre-signed url which will give temporary access.

Either way, the code is behaving as expected now. It's return a rendered image on the broswer

  • working solution:
// aws.js 

const { S3Client, ListObjectsV2Command } = require('@aws-sdk/client-s3');

const config = ({
  region:  'us-east-2',
  credentials: {
    accessKeyId: "ACCESS_KEY",
    secretAccessKey: "SECRET_ACCESS_KEY"
  }
})

const s3Client = new S3Client(config);

const getS3List = async () => {
  const command = new ListObjectsV2Command({Bucket:'test-bucket-from-nodejs-sdk'});
  const response = await s3Client.send(command);
  return response;
}
module.exports = { getS3List }

// server.js

const express = require('express');
const app = express();
app.use(express.json());
const { getS3List} = require('./aws.js');

app.get('/test', (req, res) => {
  getS3List()
    .then((data) => {
      let image = data.Contents[1].Key;
      console.log('image:', image);
      res.send(`<img src='https://test-bucket-from-nodejs-sdk.s3.us-east-2.amazonaws.com/${image}'></img>`)
    })
    .catch((err) => {
      throw err;
    })
})
  • Related