Uploading Files Directly to Amazon S3 Using AJAX

Last edit: Jul 02, 2019
  • Contributors:
  • lemingos
  • pavelloz
  • Slashek

This guide will help you use the Amazon S3 direct upload from the front-end by adding the files from form that are exposed to you for each file uploader.

This guide presents a different approach to the Uploading Files Directly to Amazon S3 Using HTML Form tutorial by uploading a file directly to the AWS S3 bucket using AJAX.

Requirements

This is an advanced tutorial. To follow it, you should be familiar with basic platformOS concepts, HTML, Liquid, APIs and Form Configurations, and the topics in the Get Started section.
This guide uses the same Form Configuration, user profile type, and page as Uploading Files Directly to Amazon S3 Using HTML Form.

Steps

Uploading content directly to Amazon S3 is a two-step process:

Step 1: Prepare HTML form with fields including required metadata

form_configurations/developer/update_profile.liquid

Create variables for quicker access later on:


{% assign profile = form.fields.profiles.developer %}
{% assign avatar = profile.custom_images.avatar %}
{% assign image_s3_upload = avatar.image.s3_upload %}

Load required javascript file that contains code responsible for making the AJAX request:


<script src="{{ 'DirectUpload.js' | asset_url }}" defer></script>

Create form, and set up all required data in hidden inputs (those will be read by JavaScript later):


<form action="{{ image_s3_upload.direct_upload_url }}"
  data-direct-upload-ajax="form">

  {% for input in image_s3_upload.form_data %}
    <input type="hidden" name="{{ input[0] }}" value="{{ input[1] }}">
  {% endfor %}

  <input type="file" name="file" id="{{ avatar.image.name }}" data-direct-upload-ajax="file">
</form>

Note

File input has to have the name file.

Step 2: Submit file using AJAX

DirectUpload.js file contains all necessary JavaScript needed to handle file sending, error, and preview display.

assets/DirectUpload.js

const $form = $('[data-direct-upload-ajax="form"]');

$('[data-direct-upload-ajax="file"]').on("change", () => {
  $.ajax({
    type: "post",
    url: $form.attr("action"), // get url from form tag
    contentType: false, // guess Content-Type header (it has to be multipart/form-data)
    processData: false, // do not try to process binary data
    data: new FormData($form[0]) // create FormData object and populate it with form element passed into constructor
  });
});

Note

Code above is stripped from non-essential parts. Source code and live example are more complete with error handling, image previews, and more.

Important notes / troubleshooting

General

  • Instead of sending an image to our server you will send a url (returned by S3 response) to the image inside the text field for given image. Image URL should look similar to https://near-me-oregon-staging.s3-us-west-2.amazonaws.com/uploads%2Fbc50d6da-c17e-477d-b143-c65422c221fd%2Ftest.3+%282%29.png
  • After form submission give our server couple of seconds to pickup your image, generate size versions, compress them and upload to the new S3 location so the CDN could pick it up for you and datatabase to be updated with CDN links

If you have problems that you cannot figure out, go to live example page, inspect whats being sent to S3 and our server respectively and find differences between your requests and those that work - the difference usually is whats broken

AWS

  • Make sure your form is using POST method
  • Make sure your form is sending data as enctype="multipart/form-data"
  • Do not include any fields that are not listed in the s3_upload key, otherwise AWS will return error 403 with message Invalid according to Policy: Extra input fields: xxx
  • Make sure file input is sent last in the form
  • Remember to set your file input name to file

Read more about aws requirements.

Live example and source code

To play with a live example, create a developer account at https://examples.platform-os.com and go to the update_profile page.

Source code can be found on GitHub.

Additional resources

Questions?

We are always happy to help with any questions you may have.