Rails file upload implementation with jQuery-File-Upload
This gem use https://github.com/blueimp/jQuery-File-Upload for upload files.
In Gemfile:
gem 'rails-uploader'
In routes:
mount Uploader::Engine => '/uploader'
Migration for ActiveRecord:
bundle exec rails g uploader:install
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)
Javascripts:
//= require uploader/application
Stylesheets:
*= require uploader/application
<%= uploader_field_tag :article, :photo %>
or FormBuilder:
<%= form.uploader_field :photo, sortable: true %>
<%= f.input :pictures, as: :uploader %>
<%= f.input :pictures, as: :uploader, input_html: { sortable: true } %>
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
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
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.
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 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!
git checkout -b my-new-feature
)git commit -am 'Added some feature'
)git push origin my-new-feature
)rspec ./spec/
Copyright © 2022 Fodojo LLC, released under the MIT license