I'm trying to implement directory uploads with jQuery File Upload plugin by Blueimp. Rails 4 is my backend, and for attachments, I'm using Carrierwave.
The issue now is that, the jquery plugin is not able to recognize the folder that I'm uploading. I already have webkitdirectory parameter passed in the input field. Can someone help me with this?
Thanks in advance.
Here's the jQuery File Upload code in application.js:
$('#fileupload').fileupload({
dataType: "script",
sequentialUploads: true,
// This function is called when a file is added to the queue;
// either via the browse button, or via drag/drop:
add: function(e, data) {
data.context = $(tmpl("template-upload", data.files[
0]))
data.context.addClass('working');
//$('.upload-status-box').addClass('working');
$('#Upload-Bar').append(data.context);
$('.upload-status-box').show();
// Listen for clicks on the cancel button
data.context.find('span.cancel-upload').click(
function() {
jqXHR.abort();
data.context.fadeOut(function() {
data.context.remove();
});
count = count - 1;
removeUploadStatusBoxOnCompletion();
});
var jqXHR = data.submit();
count = count + 1;
},
progress: function(e, data) {
if (data.context) {
$('.upload-status-box').show();
progress = parseInt((data.loaded / data.total) *
100);
var uploadMeta = parseInt(data.loaded / 1000000) +
"/" + parseInt(data.total / 1000000) +
" MB - " + progress + "%";
data.context.find('.progress-bar').css('width',
progress + '%');
data.context.find('.status').text(uploadMeta);
}
},
done: function(e, data) {
console.log(
'Your files have been uploaded successfully!'
);
// alert('Your files have been uploaded successfully! Depending on the file size, you might have to wait for a while before performing any actions.');
count = count - 1;
data.context.removeClass('working');
data.context.find('button.cancel-upload').hide();
removeUploadStatusBoxOnCompletion();
}
});
And here's my input field:
<div class="awesome-file-uploads" id="inline-upload-status">
<%= form_for [myfolder, Myfile.new], html: { multipart: true, :id => "fileupload" } do |f| %>
<%= f.file_field :attachment, multiple: true, id: "fileinput", style: "display:none;", "webkitdirectory"=> "", "directory"=> "" %>
<%= f.hidden_field :myfolder_parent_id, value: myfolder.id %>
<% end %>
Here's the code for uploading and processing the files inside the folder:
$('#folderupload').change(function(e) {
e.preventDefault();
NProgress.done();
var items = e.target.files;
var paths = ""; //
// var myfolder_id = $(this).parent();
for (var i=0, file; file=items[i]; i++) {
paths += file.webkitRelativePath+"###";
} //
// uploadFiles(items, myfolder_id.data('inside'));
$("#paths").val(paths);
$("#folderupload").submit(); //
});
function uploadFiles(items, myfolder_id){
xhr = new XMLHttpRequest();
data = new FormData();
paths = "";
var AUTH_TOKEN = $('meta[name=csrf-token]').attr('content');
data.append('authenticity_token', AUTH_TOKEN);
// Set how to handle the response text from the server
xhr.onreadystatechange = function(ev){
console.debug(xhr.responseText);
};
for (var i=0, file; file=items[i]; i++) {
paths += file.webkitRelativePath+"###";
data.append(i, file);
}
data.append('paths', paths);
xhr.open('POST', "/myfolders/"+myfolder_id+"/create_from_folder", true);
xhr.send(this.data);
}
Hi its very easy to use blueimp file upload in rails. Simply you can install gems available for blueimp file upload.Famous are Carrierwave gem & Dragonfly gem. If you have one of this gems , you can use following steps to work on blueimp
Prerequisites
have jQuery setup in your app
copy jQuery File Upload files in the proper directories of your Rails app
Models For use with the Carrierwave gem
We'll use basic Carrierwave uploader:
class AvatarUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
Let's set up a Picture model
class Picture < ActiveRecord::Base
include Rails.application.routes.url_helpers
mount_uploader :avatar, AvatarUploader
#one convenient method to pass jq_upload the necessary information
def to_jq_upload
{
"name" => read_attribute(:avatar),
"size" => avatar.size,
"url" => avatar.url,
"thumbnail_url" => avatar.thumb.url,
"delete_url" => picture_path(:id => id),
"delete_type" => "DELETE"
}
end
end
For use with the Dragonfly gem
set up a Picture model (make sure you have both avatar_uid and avatar_name columns in your database)
class Picture < ActiveRecord::Base
include Rails.application.routes.url_helpers
image_accessor :avatar
#one convenient method to pass jq_upload the necessary information
def to_jq_upload
{
"name" => read_attribute(:avatar_name),
"size" => avatar.size,
"url" => avatar.url,
"thumbnail_url" => avatar.thumb('80x80#').url,
"delete_url" => picture_path(:id => id),
"delete_type" => "DELETE"
}
end
end
Controller
First one controller to handle the downloads: (html response is for browsers using iframe sollution)
class PicturesController < ApplicationController
def index
@pictures = Picture.all
render :json => @pictures.collect { |p| p.to_jq_upload }.to_json
end
def create
@picture = Picture.new(params[:picture])
if @picture.save
respond_to do |format|
format.html {
render :json => [@picture.to_jq_upload].to_json,
:content_type => 'text/html',
:layout => false
}
format.json {
render :json => [@picture.to_jq_upload].to_json
}
end
else
render :json => [{:error => "custom_failure"}], :status => 304
end
end
def destroy
@picture = Picture.find(params[:id])
@picture.destroy
render :json => true
end
end
And it's routes:
resources :pictures, :only => [:index, :create, :destroy]
Let's play
In whatever view file you want, copy paste this code and enjoy.
<h2><%= t('photos.title') %></h2>
<%= form_for Picture.new, :html => { :multipart => true, :id => "fileupload" } do |f| %>
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="span7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="icon-plus icon-white"></i>
<span>Add files...</span>
<%= f.file_field :avatar %>
</span>
<button type="submit" class="btn btn-primary start">
<i class="icon-upload icon-white"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="icon-ban-circle icon-white"></i>
<span>Cancel upload</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="icon-trash icon-white"></i>
<span>Delete</span>
</button>
<input type="checkbox" class="toggle">
</div>
<div class="span5">
<!-- The global progress bar -->
<div class="progress progress-success progress-striped active fade">
<div class="bar" style="width:0%;"></div>
</div>
</div>
</div>
<!-- The loading indicator is shown during image processing -->
<div class="fileupload-loading"></div>
<br>
<!-- The table listing the files available for upload/download -->
<table class="table table-striped"><tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody>
</table>
<% end %>
<script>
var fileUploadErrors = {
maxFileSize: 'File is too big',
minFileSize: 'File is too small',
acceptFileTypes: 'Filetype not allowed',
maxNumberOfFiles: 'Max number of files exceeded',
uploadedBytes: 'Uploaded bytes exceed file size',
emptyResult: 'Empty file upload result'
};
</script>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td class="preview"><span class="fade"></span></td>
<td class="name"><span>{%=file.name%}</span></td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
{% if (file.error) { %}
<td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
{% } else if (o.files.valid && !i) { %}
<td>
<div class="progress progress-success progress-striped active"><div class="bar" style="width:0%;"></div></div>
</td>
<td class="start">{% if (!o.options.autoUpload) { %}
<button class="btn btn-primary">
<i class="icon-upload icon-white"></i>
<span>{%=locale.fileupload.start%}</span>
</button>
{% } %}</td>
{% } else { %}
<td colspan="2"></td>
{% } %}
<td class="cancel">{% if (!i) { %}
<button class="btn btn-warning">
<i class="icon-ban-circle icon-white"></i>
<span>{%=locale.fileupload.cancel%}</span>
</button>
{% } %}</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
{% if (file.error) { %}
<td></td>
<td class="name"><span>{%=file.name%}</span></td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
{% } else { %}
<td class="preview">{% if (file.thumbnail_url) { %}
<a href="{%=file.url%}" title="{%=file.name%}" rel="gallery" download="{%=file.name%}"><img src="{%=file.thumbnail_url%}"></a>
{% } %}</td>
<td class="name">
<a href="{%=file.url%}" title="{%=file.name%}" rel="{%=file.thumbnail_url&&'gallery'%}" download="{%=file.name%}">{%=file.name%}</a>
</td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td colspan="2"></td>
{% } %}
<td class="delete">
<button class="btn btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">
<i class="icon-trash icon-white"></i>
<span>{%=locale.fileupload.destroy%}</span>
</button>
<input type="checkbox" name="delete" value="1">
</td>
</tr>
{% } %}
</script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<%= javascript_include_tag 'jquery.ui.widget.js' %>
<!-- The Templates and Load Image plugins are included for the FileUpload user interface -->
<script src="https://blueimp.github.com/JavaScript-Templates/tmpl.min.js"></script>
<script src="https://blueimp.github.com/JavaScript-Load-Image/load-image.all.min.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<%= javascript_include_tag 'jquery.iframe-transport.js' %>
<%= javascript_include_tag 'jquery.fileupload.js' %>
<%= javascript_include_tag 'jquery.fileupload-ui.js' %>
<!-- add include_tag js files to config.assets.precompile in ...environments/production.rb if you have it in vendor/ assets -->
<script type="text/javascript" charset="utf-8">
$(function () {
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload();
//
// Load existing files:
$.getJSON($('#fileupload').prop('action'), function (files) {
var fu = $('#fileupload').data('blueimp-fileupload'),
template;
fu._adjustMaxNumberOfFiles(-files.length);
template = fu._renderDownload(files)
.appendTo($('#fileupload .files'));
// Force reflow:
fu._reflow = fu._transition && template.length &&
template[0].offsetWidth;
template.addClass('in');
$('#loading').remove();
});
});
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With