S3DirectUpload

Easily generate a form that allows you to upload directly to Amazon S3. Multi file uploading supported by jquery-fileupload.

Code extracted from Ryan Bates' gallery-jquery-fileupload.

Installation

Add this line to your application's Gemfile:

gem 's3_direct_upload'

Then add a new initalizer with your AWS credentials:

config/initalizers/s3_direct_upload.rb

S3DirectUpload.config do |c|
  c.access_key_id = ""       # your access key id
  c.secret_access_key = ""   # your secret access key
  c.bucket = ""              # your bucket name
end

Make sure your AWS S3 CORS settings for your bucket look something like this:

<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>http://0.0.0.0:3000</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

In production the AllowedOrigin key should be your domain.

Add the following js and css to your asset pipeline:

application.js

//= require s3_direct_upload

application.css

//= require s3_direct_upload_progress_bars

Usage

Create a new view that uses the helper:

<%= s3_uploader_form post: model_url, as: "model[image_url]" do %>
  <%= file_field_tag :file, multiple: true %>
<% end %>

Also place this template in the same view for the progress bars:

<script id="template-upload" type="text/x-tmpl">
<div class="upload">
  {%=o.name%}
  <div class="progress"><div class="bar" style="width: 0%"></div></div>
</div>
</script>

Customizations

Feel free to override the styling for the progress bars in s3_direct_upload_progress_bars, look at the source for inspiration.

Also feel free to write your own js to interface with jquery-file-upload. You might want to do this to do custom validations on the files before it is sent to S3 for example. To do this remove s3_direct_upload from your application.js and include the necissary jquery-file-upload scripts (they are included in this gem automatically):

//= require jquery-fileupload/basic
//= require jquery-fileupload/vendor/tmpl

and use the s3_direct_upload script as a guide, the form helper will still work fine if thats all you need.

s3_uploader_form options and after upload callback

After the upload is complete, the script will execute an ajax POST to the model_url given in the post option in the form helper. The url to the file on S3 will be passed as a key to whatever is in the as option.

You could have your create action render a javascript file like this:

create.js.erb

<% if @model.new_record? %>
  alert("Failed to upload model: <%= j @model.errors.full_messages.join(', ').html_safe %>");
<% else %>
  $("#paintings").append("<%= j render(@model) %>");
<% end %>

So that javascript code would be executed after the model instance is created, which would render your _model.html.erb template without a page reload if you wish.

It is recommended that you persist the image_url as an attribute on the model. To do this To do this add resources model in the routes file, and add the 'image_url' attribute to your model (can be whatever you set it as in the as options)

Gotchas

Right now you can only have one upload form on a page. Upload form is hardcoded with id '#fileupload'

Contributing / TODO

This is just a simple gem that only really provides some javascript and a form helper. This gem could go all sorts of ways based on what people want and how people contribute. Ideas: More specs! More options to control expiration, max filesize, file types etc. Create generators. Model methods.

Credit

This gem is basically a small wrapper around code that Ryan Bates wrote for Railscast#383. Most of the code in this gem was extracted from gallery-jquery-fileupload.

Thank you Ryan Bates!

This code also uses the excellecnt jQuery-File-Upload, which is included in this gem by its rails counterpart jquery-fileupload-rails