Display AWS S3 files from signed URLs

This example explains how to display pictures stored in an AWS S3 bucket, from signed URLs.

Below we have a collection places with a field pictures which is an array of strings containing the names of files stored in an S3 bucket on AWS.

We use then a smart field s3Pictures that is an array of return values from calls made to S3 to get signed URLs from the files present in pictures field.

Requirements

  • An admin backend running on forest-express-sequelize

  • An AWS S3 bucket with access credentials

  • The aws-sdk npm package

How it works

Directory: /models

This directory contains the places.js file where the places model is declared.

places.js
module.exports = (sequelize, DataTypes) => {
const { Sequelize } = sequelize;
const Places = sequelize.define('places', {
name: {
type: DataTypes.STRING,
},
address: {
type: DataTypes.STRING,
},
pictures: {
type: DataTypes.ARRAY(DataTypes.STRING),
},
}, {
tableName: 'places',
underscored: true,
timestamps: false,
});
return Places;
};

Directory: /services

This directory contains an s3-helper.js file, where the method to get the signed URL from S3 is defined. We use the aws-sdk npm package to connect to the bucket storing the pictures.

You need to configure your AWS credentials inside your app to get access to your bucket. You can read more about it in the AWS documentation here.

const AWS = require('aws-sdk');
// Retrieving the AWS credentials from `.env` file
AWS.config.update({
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
});
function getS3SignedUrlById(fileId) {
const s3Bucket = new AWS.S3({ params: { Bucket: process.env.S3_BUCKET } });
return s3Bucket.getSignedUrl("getObject", {
Key: fileId,
Expires: 60 * process.env.AWS_S3_URL_EXPIRE_MINS,
});
}
module.exports = getS3SignedUrlById;

Directory: /forest

This directory contains the places.js file where the smart field s3Pictures is declared.

In the get function, we iterate on the pictures array to get the signed URL for each file name and then return an array with the signed URLs.

You can then use the file viewer widget to preview the pictures.

places.js
const { collection } = require('forest-express-sequelize');
const getSignedUrlById = require('../services/s3-helper');
collection('places', {
actions: [],
fields: [
{
field: 's3Pictures',
type: ['String'],
get: (place) => {
if (place.pictures) {
const s3pictures = place.pictures.map((pic) => getS3SignedUrlById(pic))
return Promise.all(s3pictures)
}
return null;
},
},
],
segments: [],
});