Rails 4: How to upload files with AJAX Rails 4: How to upload files with AJAX ajax ajax

Rails 4: How to upload files with AJAX


Have a look into the remotipart gem: https://github.com/JangoSteve/remotipart -- may get you all of the way there with very little work!


IMHO Rails is not perfect when dealing with upload files using AJAX, especially if you want a progress bar. My suggestion is to use Javascript for the form submission over an AJAX request like you suggested in (2). If you are comfortable with Javascript you will not have many problems.

I recently used the same approach by using this very simple JS library https://github.com/hayageek/jquery-upload-file and I wrote more details here http://www.alfredo.motta.name/upload-video-files-with-rails-paperclip-and-jquery-upload-file/

For an application with a form to upload a movie with title and description the JS code looks like follow:

$(document).ready(function() {  var uploadObj = $("#movie_video").uploadFile({    url: "/movies",    multiple: false,    fileName: "movie[video]",    autoSubmit: false,    formData: {      "movie[title]": $('#movie_title').text(),      "movie[description]": $('#movie_description').text()    },    onSuccess:function(files,data,xhr)    {      window.location.href = data.to;    }  });  $("#fileUpload").click(function(e) {    e.preventDefault();    $.rails.disableFormElements($($.rails.formSubmitSelector));    uploadObj.startUpload();  });});

Far from perfect, but gives you flexibility on your frontend.


Using @rails/ujs.

view (.html.erb):

<%= file_field_tag :file, { id: "ajax_file_upload"} %>

controller(_controller.rb):

def update  @record = YourModel.find(params[:id])  respond_to do |format|    if @record.update_attributes(params[:your_model])      format.json { render json: { success: true } }    else      error_messages = @record.errors.messages.values.flatten      format.json { render json: { success: false, errors: error_messages } }    end  endend

javascript(.js)

const uploadFile = element => {  const formData = new FormData();  formData.append("your_model[attribute_name]", element.target.files[0]);  Rails.ajax({    url: "your_model/:id",    type: "PUT",    beforeSend(xhr, options) {      options.data = formData;      return true;    },    success: response => {      if (response.success) {        alert("File uploaded successfully");      }      else {        alert(response.errors.join("<br>"));      }    },    error: () => {      alert("ajax send error");    }  });};const documentOnReady = () => {  const fileField = document.getElementById("ajax_file_upload");  if (fileField) {    fileField.addEventListener("change", uploadFile);  }}document.addEventListener("turbolinks:load", documentOnReady);

Note: No need to setRequestHeader in ajax while using FormData.

FormData uses the same format a form would use if the encoding type were set to "multipart/form-data"