Direct Upload on S3 throws error : No 'Access-Control-Allow-Origin' header is present on the requested resource
Not solved Solved
about 2 years ago

Hi everybody, I have been trying to implement direct upload to S3 on my app following these instructions :

So I have a form where the user can upload a picture and it looks like this with the code provided in the tutorial :

<%= form_for(@hotel,  url: account_hotels_path(params[:account_id]), html: { class: 'directUpload', data: { 'form-data' => (@s3_direct_post.fields), 'url' => @s3_direct_post.url, 'host' => URI.parse(@s3_direct_post.url).host } }) do |f| %>
  <%= f.hidden_field :account_id, :value => params[:account_id] %>
  <div class="form-group">
    <%= f.label :city %>
    <%= f.text_field :city %>
  <div class="form-group">
    <%= f.label :postcode %>
    <%= f.text_field :postcode %>
  <div class="form-group">
    <%= label_tag "Number of rooms" %>
    <%= number_field_tag "room_number"%>
  <div class="form-group">
    <%= label_tag "Number of Beds in each room" %>
    <%= number_field_tag "bed_number"%>
  <div class="field">
    <%= f.label "Photo" %><br>
    <%= f.file_field "photo[image_url]" %>
   <div class="form-group">
    <%= f.submit %>
<% end %>  
<% content_for(:after_js) do %>
   $('.directUpload').find("input:file").each(function(i, elem) {
      var fileInput    = $(elem);
      var form         = $(fileInput.parents('form:first'));
      var submitButton = form.find('input[type="submit"]');
      var progressBar  = $("<div class='bar'></div>");
      var barContainer = $("<div class='progress'></div>").append(progressBar);
        fileInput:       fileInput,
        url:   'url'),
        type:            'POST',
        autoUpload:       true,
        paramName:        'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
        dataType:         'XML',  // S3 returns XML if success_action_status is set to 201
        replaceFileInput: false,
        progressall: function (e, data) {
        var progress = parseInt(data.loaded / * 100, 10);
        progressBar.css('width', progress + '%')
      start: function (e) {
        submitButton.prop('disabled', true);

          css('background', 'green').
          css('display', 'block').
          css('width', '0%').
      done: function(e, data) {
        submitButton.prop('disabled', false);
        progressBar.text("Uploading done");

        // extract key and generate URL from response
        var key   = $(data.jqXHR.responseXML).find("Key").text();
        var url   = '//' +'host') + '/' + key;

        // create hidden field
        var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
      fail: function(e, data) {
        submitButton.prop('disabled', false);

          css("background", "red").
<% end -%>

However when my user uploads a file I get the following error :

XMLHttpRequest cannot load Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

I know this error might be due to the CORS configuration of my bucket but I have updated it according to the tutorial instructions :

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="">

What is going wrong here ? If some of you want to gain some extra points on SO, it's here :

about 2 years ago

looks like localhost:3000 is not accepted by s3 with direct upload...? Try with ngrok to see if you get the same error @davidgeismar

about 2 years ago

@krokrob it doesnt work better with ngrock :(. I still get the same error I also tried to change my CORS config on my bucket to : <AllowedOrigin>*</AllowedOrigin>

Submit your answer