0.05
A long-lived project that still receives updates
Rails HTML5 FileUpload helpers
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

Build Status

HTML5 File uploader for rails

This gem use https://github.com/blueimp/jQuery-File-Upload for upload files.

Install

In Gemfile:

gem 'rails-uploader'

In routes:

mount Uploader::Engine => '/uploader'

Migration for ActiveRecord:

bundle exec rails g uploader:install

Usage

Architecture to store uploaded files (cancan integration):

class Asset < ActiveRecord::Base
  include Uploader::Asset
end

class Picture < Asset
  mount_uploader :data, PictureUploader, mount_on: :data_file_name
  validates :data, file_size: { maximum: 5.megabytes.to_i }

  def thumb_url
    url(:thumb)
  end
end

class PictureUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  storage :file

  version :thumb do
    process resize_to_fill: [100, 100]
  end

  def extension_whitelist
    %w[jpg jpeg gif png]
  end
end

For example user has one picture:

class User < ActiveRecord::Base
  has_one :picture, as: :assetable, dependent: :destroy

  fileuploads :picture
end

Find asset by foreign key or guid:

@user.fileupload_asset(:picture)

Include assets

Javascripts:

//= require uploader/application

Stylesheets:

*= require uploader/application

Views

<%= uploader_field_tag :article, :photo %>

or FormBuilder:

<%= form.uploader_field :photo, sortable: true %>

Formtastic

<%= f.input :pictures, as: :uploader %>

SimpleForm

<%= f.input :pictures, as: :uploader, input_html: { sortable: true } %>

Confirming deletions

This is only working in Formtastic and FormBuilder:

# formtastic
<%= f.input :picture, :as => :uploader, :confirm_delete => true %>
# the i18n lookup key would be en.formtastic.delete_confirmations.picture

Authorization

Setup custom authorization adapter and current user:

# config/initializers/uploader.rb
Uploader.setup do |config|
  config.authorization_adapter = CanCanUploaderAdapter
  config.current_user_proc = -> (request) { request.env['warden'].user }
end

CanCanUploaderAdapter class just create cancan ability object and call can? method with same args:

class CanCanUploaderAdapter < Uploader::AuthorizationAdapter
  def authorized?(action, subject = nil)
    cancan_ability.can?(action, subject)
  end

  def scope_collection(collection, action = :index)
    collection.accessible_by(cancan_ability, action)
  end

  protected

  def cancan_ability
    @cancan_ability ||= Ability.new(user)
  end
end

JSON Response

https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#using-jquery-file-upload-ui-version-with-a-custom-server-side-upload-handler

Extend your custom server-side upload handler to return a JSON response akin to the following output:

{"files": [
  {
    "name": "picture1.jpg",
    "size": 902604,
    "url": "http:\/\/example.org\/files\/picture1.jpg",
    "thumb_url": "http:\/\/example.org\/files\/thumbnail\/picture1.jpg",
    "id": 1,
    "content_type": "image/jpg"
  },
  {
    "name": "picture2.jpg",
    "size": 841946,
    "url": "http:\/\/example.org\/files\/picture2.jpg",
    "thumb_url": "http:\/\/example.org\/files\/thumbnail\/picture2.jpg",
    "id": 2,
    "content_type": "image/jpg"
  }
]}

To return errors to the UI, just add an error property to the individual file objects:

{"files": [
  {
    "name": "picture1.jpg",
    "size": 902604,
    "error": "Filetype not allowed"
  },
  {
    "name": "picture2.jpg",
    "size": 841946,
    "error": "Filetype not allowed"
  }
]}

When removing files using the delete button, the response should be like this:

{"files": [
  {
    "picture1.jpg": true
  },
  {
    "picture2.jpg": true
  }
]}

Note that the response should always be a JSON object containing a files array even if only one file is uploaded.

Customize JSON response and views

To customize JSON response just overwrite to_fileupload method:

class Asset
  include Uploader::Asset

  def to_fileupload
    {
      id: id,
      name: filename,
      content_type: content_type,
      size: size,
      url:  url,
      thumb_url: thumb_url
    }
  end
end

For exsample let's overwrite id method to public_token method:

class Asset
  include Uploader::Asset

  def to_fileupload
    super.merge(id: public_token)
  end

  def self.fileupload_find_asset(params)
    where(public_token: params[:id]).first
  end
end

To customize views just create new theme. For example create avatar theme:

app/views/uploader/avatar/_container.html.erb
app/views/uploader/avatar/_download.html.erb
app/views/uploader/avatar/_upload.html.erb

And pass theme to input field:

= form.uploader_field :photo, theme: 'avatar'

Chunked file uploads

Chunked file uploads are only supported by browsers with support for XHR file uploads and the Blob API, which includes Google Chrome and Mozilla Firefox 4+.

To upload large files in smaller chunks, set the max_chunk_size option to a preferred maximum chunk size in Bytes:

= f.uploader_field :video, data: { max_chunk_size: 10_000_000 }

That's it!

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Testing

rspec ./spec/

Copyright (c) 2022 Fodojo LLC, released under the MIT license