S3 File Field Build Status

jQuery File Upload extension for direct uploading to Amazon S3 using CORS

Works as an extension of jQuery File Upload JavaScript plugin and supports IE 7-10.

It supports multiple upload, and per-input configuration.

Installation

Gemfile

gem 's3_file_field'

application.coffee

#= require s3_file_field

config/initializers/s3_file_field.rb

S3FileField.config do |c|
  c.access_key_id = ENV['AWS_ACCESS_KEY_ID']
  c.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
  c.bucket = ENV['AWS_BUCKET']
  # c.acl = "public-read"
  # c.expiration = 10.hours.from_now.utc.iso8601
  # c.max_file_size = 500.megabytes
  # c.conditions = []
  # c.key_starts_with = 'uploads/
  # c.ssl = true # if unset or false, will default to current server settings
end

S3 configuration

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

<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

In production the AllowedOrigin key should be your base url like http://example.com

Also ensure you've added PutObject and PutObjectAcl permission in your bucket policy. Here is mine:

{
  "Version": "2008-10-17",
  "Id": "Policy1372930880859",
  "Statement": [
    {
      "Sid": "Stmt1372930877007",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObjectAcl",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::BUCKET_NAME/*"
    }
  ]
}

Basic usage

= form_for :user do |f|
  = f.s3_file_field :avatar, :class => 'js-s3_file_field'
  .progress
    .meter{ :style => "width: 0%" }
jQuery.ready ->
  $('.js-s3_file_field').S3FileField
    done: (e, data) -> console.log(data.result.url)

Advanced usage

= form_for :user do |f|
  = f.s3_file_field :avatar,
    :class => 'js-s3_file_field',
    :key => "/uploads/${timestamp}/${filename}"
  .progress
    .meter{ :style => "width: 0%" }
ready = ->
  $(".js-s3_file_field").each ->
    id = $(this).attr('id')
    $this = -> $("##{id}")
    $progress = $(this).siblings('.progress').hide()
    $meter = $progress.find('.meter')
    $(this).S3FileField
      add: (e, data) ->
        $progress.show()
        data.submit()
      done: (e, data) ->
        $progress.hide()
        $this().attr(type: 'text', value: data.result.url, readonly: true)
      fail: (e, data) ->
        alert(data.failReason)
      progress: (e, data) ->
        progress = parseInt(data.loaded / data.total * 100, 10)
        $meter.css(width: "#{progress}%")

$(document).ready(ready)
$(document).on('page:load', ready)

Advanced customization

You can use any options / API available for jQuery File Upload plugin.

For full list of options reference jQuery File Field wiki page

After successful upload, you'll find file data in data.result field:

{
  "url": "https://foobar.s3.amazonaws.com/uploads/v3w3qzcb1d78pvi/something.gif",
  "filepath": "uploads/v3w3qzcb1d78pvi/something.gif",
  "filename": "something.gif",
  "filesize": 184387,
  "filetype": "image\/gif",
  "unique_id": "v3w3qzcb1d78pvi"
}

Cleaning old uploads on S3

Check out this article on Lifecycle Configuration.

Thanks

License

This repository is MIT-licensed. You are awesome.

Bitdeli Badge