Uploading Files Directly to Amazon S3 Using AJAX

Last edit: Aug 16, 2019
  • Contributors:
  • Slashek
  • pavelloz

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.


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


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

Step 1: Prepare HTML form with fields including required metadata


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 }}"

  {% 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">


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.


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

$('[data-direct-upload-ajax="file"]').on("change", () => {
    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


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


  • 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


  • 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


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