Woodshop for old agent generation
Try the new agent generation
  • What is woodshop
  • How to's
    • Smart Relationship
      • GetIdsFromRequest
    • Smart views
      • Display a calendar view
      • Create a custom tinder-like validation view
      • Create a custom moderation view
      • Create a dynamic calendar view for an event-booking use case
    • Configure environment variables
      • NodeJS/Express projects
    • Elasticsearch Integration
      • Interact with your Elasticsearch data
      • Elasticsearch service/utils
      • Another example
    • Zendesk Integration
      • Authentication, Filtering & Sorting
      • Display Zendesk tickets
      • Display Zendesk users
      • View tickets related to a user
      • Bonus: Direct link to Zendesk + change priority of a ticket
    • Dwolla integration
      • Display Dwolla customers
      • Display Dwolla funding sources
      • Display Dwolla transfers
      • Link users and Dwolla customers
      • Dwolla service
    • Make filters case insensitive
    • Use Azure Table Storage
    • Create multiple line charts
    • Create Charts with AWS Redshift
    • View soft-deleted records
    • Send Smart Action notifications to Slack
    • Authenticate a Forest Admin API against an OAuth protected API Backend
    • Translate your project into TypeScript
      • V8
        • Migrate Mongoose files
        • Migrate Sequelize files
      • v7
        • Migrate Mongoose files
        • Migrate Sequelize files
      • v6
    • Geocode an address with Algolia
    • Display/edit a nested document
    • Send an SMS with Zapier
    • Hash a password with bcrypt
    • Display a customized response
    • Search on a smart field with two joints
    • Override the count route
    • Make a field readOnly with Sequelize
    • Hubspot integration
      • Create a Hubspot company
      • Display Hubspot companies
    • Impersonate a user
    • Import data from a CSV file
    • Import data from a JSON file
    • Load smart fields using hook
    • Pre-fill a form with data from a relationship
    • Re-use a smart field logic
    • Link to record info in a smart view
    • Display data in html format
    • Upload files to AWS S3
    • Display AWS S3 files from signed URLs
    • Prevent record update
    • Display, search and update attributes from a JSON field
    • Add many existing records at the same time (hasMany-belongsTo relationship)
    • Track users’ logs with morgan
    • Search on relationship fields by default
    • Export related data as CSV
    • Run automated tests
  • Forest Admin Documentation
Powered by GitBook
On this page
  • Requirements
  • How it works
  • Directory: /models
  • Directory: /forest
  • Directory: /services
  • Directory: /routes

Was this helpful?

  1. How to's

Upload files to AWS S3

PreviousDisplay data in html formatNextDisplay AWS S3 files from signed URLs

Last updated 4 years ago

Was this helpful?

This example shows you how to implement a smart action to upload image files to an AWS S3 bucket. Here we have a companies model that has two fields corresponding to files stored in an AWS S3 bucket:

  • A certificate of incorporation

  • A proof of identity

We implemented a smart action to upload the files for each company.

Requirements

  • An admin backend running on forest-express-sequelize

  • An AWS S3 bucket with access credentials

How it works

Directory: /models

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

module.exports = (sequelize, DataTypes) => {
  const { Sequelize } = sequelize;
  const Companies = sequelize.define('companies', {
    name: {
      type: DataTypes.STRING,
    },
    industry: {
      type: DataTypes.STRING,
    },
    headquarter: {
      type: DataTypes.STRING,
    },
    status: {
      type: DataTypes.STRING,
    },
    description: {
      type: DataTypes.STRING,
    },
    createdAt: {
      type: DataTypes.DATE,
    },
    updatedAt: {
      type: DataTypes.DATE,
    },
    certificateOfIncorporationId: {
      type: DataTypes.UUID,
    },
    passportId: {
      type: DataTypes.UUID,
    },
  }, {
    tableName: 'companies',
    underscored: true,
    schema: process.env.DATABASE_SCHEMA,
  });

  return Companies;
};

Directory: /forest

This directory contains the companies.js file where the smart action Upload Legal Docs is declared.

You need to specify that the widget file picker is applicable to the input field used to upload the file.

companies.js
const { collection } = require('forest-express-sequelize');

collection('companies', {
  actions: [
    {
      name: 'Upload Legal Docs',
      type: 'single',
      fields: [{
        field: 'Certificate of Incorporation',
        description: 'The legal document relating to the formation of a company or corporation.',
        type: 'File',
        isRequired: true,
      }, {
        field: 'Valid proof of ID',
        description: 'ID card or passport if the document has been issued in the EU, EFTA, or EEA / ID card or passport + resident permit or driving licence if the document has been issued outside the EU, EFTA, or EEA of the legal representative of your company',
        type: 'File',
        isRequired: true,
      }],
    },
  ],
  fields: [],
  segments: [],
});

Directory: /services

This directory contains an s3-helper.js file where the methods to upload files to s3 is declared.

const P = require('bluebird');
const parseDataUri = require('parse-data-uri');
const AWS = require('aws-sdk');

function S3Helper() {
  this.upload = (rawData, filename) => new P((resolve, reject) => {
    // Create the S3 client.
    const s3Bucket = new AWS.S3({ params: { Bucket: process.env.S3_BUCKET } });
    const parsed = parseDataUri(rawData);

    const data = {
      Key: filename,
      Body: parsed.data,
      ContentDisposition: 'inline',
      ContentType: parsed.mimeType,
    };
    
    // Upload the image.
    s3Bucket.upload(data, (err, response) => {
      if (err) {
        return reject(err);
      }
      return resolve(response);
    });
  });
}

module.exports = S3Helper;

Directory: /routes

This directory contains the companies.js file where the logic of the smart action is implemented.

companies.js
const express = require('express');
const { PermissionMiddlewareCreator } = require('forest-express-sequelize');
const { companies } = require('../models');
const uuid = require('uuid/v4');
const S3Helper = require('../services/s3-helper');
const P = require('bluebird');


const router = express.Router();
const permissionMiddlewareCreator = new PermissionMiddlewareCreator('companies');

function uploadLegalDoc(companyId, doc, field) {
  const id = uuid();
  //upload the files using the helper
  return new S3Helper().upload(doc, `livedemo/legal/${id}`)
  //once the file is uploaded, update the relevant company field with the file id
    .then(() => companies.findByPk(companyId))
    .then((company) => {
      company[field] = id;
      return company.save();
    })
    .catch((e) => e);
}

router.post('/actions/upload-legal-docs', permissionMiddlewareCreator.smartAction(), (req, res) => {
  // Get the current company id
  const companyId = req.body.data.attributes.ids[0];

  // Get the values of the input fields entered by the admin user.
  const attrs = req.body.data.attributes.values;
  const certificateOfIncorporation = attrs['Certificate of Incorporation'];
  const passportId = attrs['Valid proof of ID'];

  P.all([
    uploadLegalDoc(companyId, certificateOfIncorporation, 'certificateOfIncorporationId'),
    uploadLegalDoc(companyId, passportId, 'passportId'),
  ])
    .then(() => {
      // Once the upload is finished, send a success message to the admin user in the UI.
      return res.send({ success: 'Legal documents are successfully uploaded.' });
    });
});

module.exports = router;

The npm package

The npm package

The npm package

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 .

aws-sdk
bluebird
parse-data-uri
here