# 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: ``` ruby mount Uploader::Engine => '/uploader' ``` Migration for ActiveRecord: ```bash $> rake uploader:install:migrations ``` ## Usage Architecture to store uploaded files (cancan integration): ``` ruby 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 ``` For example user has one picture: ``` ruby class User < ActiveRecord::Base has_one :picture, as: :assetable, dependent: :destroy fileuploads :picture end ``` Find asset by foreign key or guid: ``` ruby @user.fileupload_asset(:picture) ``` ### Include assets Javascripts: ``` //= require uploader/application ``` Stylesheets: ``` *= require uploader/application ``` ### Views ```erb <%= uploader_field_tag :article, :photo %> ``` or FormBuilder: ```erb <%= form.uploader_field :photo, sortable: true %> ``` ### Formtastic ```erb <%= f.input :pictures, as: :uploader %> ``` ### SimpleForm ```erb <%= f.input :pictures, as: :uploader, input_html: { sortable: true } %> ``` #### Confirming deletions This is only working in Formtastic and FormBuilder: ``` erb # 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: ``` ruby # 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: ``` ruby 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: ``` json {"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: ``` json {"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: ``` json {"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: ``` ruby 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: ``` ruby 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: ``` slim = 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: ``` slim = 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) 2016 Fodojo LLC, released under the MIT license