I am using basic plus of jquery file upload, and i am trying to have one upload button to upload multiple files at same time but its current showing multiple upload buttons if i select multiple files, you can see try it online at here
HTML Code
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<!-- The file input field used as target for the file upload widget -->
<input id="fileupload" type="file" name="files[]" multiple>
</span>
<br>
<br>
<!-- The global progress bar -->
<div id="progress" class="progress">
<div class="progress-bar progress-bar-success"></div>
</div>
<!-- The container for the uploaded files -->
<div id="files" class="files"></div>
JS Code
$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
var url = '',
uploadButton = $('<button/>')
.addClass('btn btn-primary')
.prop('disabled', true)
.text('Processing...')
.on('click', function () {
var $this = $(this),
data = $this.data();
$this
.off('click')
.text('Abort')
.on('click', function () {
$this.remove();
data.abort();
});
data.submit().always(function () {
$this.remove();
});
});
$('#fileupload').fileupload({
url: url,
dataType: 'json',
autoUpload: false,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 5000000, // 5 MB
// Enable image resizing, except for Android and Opera,
// which actually support image resizing, but fail to
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true
}).on('fileuploadadd', function (e, data) {
data.context = $('<div/>').appendTo('#files');
$.each(data.files, function (index, file) {
var node = $('<p/>')
.append($('<span/>').text(file.name));
if (!index) {
node
.append('<br>')
.append(uploadButton.clone(true).data(data));
}
node.appendTo(data.context);
});
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index,
file = data.files[index],
node = $(data.context.children()[index]);
if (file.preview) {
node
.prepend('<br>')
.prepend(file.preview);
}
if (file.error) {
node
.append('<br>')
.append($('<span class="text-danger"/>').text(file.error));
}
if (index + 1 === data.files.length) {
data.context.find('button')
.text('Upload')
.prop('disabled', !!data.files.error);
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}).on('fileuploaddone', function (e, data) {
$.each(data.result.files, function (index, file) {
if (file.url) {
var link = $('<a>')
.attr('target', '_blank')
.prop('href', file.url);
$(data.context.children()[index])
.wrap(link);
} else if (file.error) {
var error = $('<span class="text-danger"/>').text(file.error);
$(data.context.children()[index])
.append('<br>')
.append(error);
}
});
}).on('fileuploadfail', function (e, data) {
$.each(data.files, function (index) {
var error = $('<span class="text-danger"/>').text('File upload failed.');
$(data.context.children()[index])
.append('<br>')
.append(error);
});
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
});
Its working but shows multiple upload buttons if i select multiple files to upload but i want to have one upload button which can process all uploaded files at same time. Thanks for your help.
Related
I am using Jquery file upload and compressing code for images with this i can select multiple images but it only compressing and uploading the last image selected
so how can i upload multiple images with compression? What modifications are needed plzz suggest.
Html code:
<input id="fileupload" type="file" name="file" multiple>
Jquery code:
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(function () {
'use strict';
var csrftoken = $.cookie('csrftoken');
var url = '/dashboard/{{name}}/{{name_product_type.type_product|urlencode}}/{{abc}}/';
$('#postbtn').on('click', function () {
var $this = $(this),
data = $this.data();
$this
.off('click')
.text('Abort')
.on('click', function () {
$this.remove();
data.abort();
});
data.submit().always(function () {
$this.remove();
});
});
$('#fileupload').fileupload({
url: url,
crossDomain: false,
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
dataType: 'json',
uploadMultiple: true, // allow multiple upload
autoProcessQueue: false, // prevent dropzone from uploading automatically
maxFiles: 5,
autoUpload: false,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 5000000, // 5 MB
// Enable image resizing, except for Android and Opera,
// which actually support image resizing, but fail to
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true
}).on('fileuploadadd', function (e, data) {
data.context = $('<div/>').appendTo('#files');
$.each(data.files, function (index, file) {
var node = $('<p/>')
.append($('<span/>').text(file.name));
if (!index) {
node
.append('<br>')
// .append($('#postbtn').clone(true).data(data));
}
node.appendTo(data.context);
});
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index,
file = data.files[index],
node = $(data.context.children()[index]);
if (file.preview) {
node
.prepend('<br>')
.prepend(file.preview);
}
if (file.error) {
node
.append('<br>')
.append(file.error);
}
if (index + 1 === data.files.length) {
data.context.find($('#postbtn').data(data));
// .text('Upload')
// .prop('disabled', !!data.files.error);
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}).on('fileuploaddone', function (e, data) {
$.each(data.result.files, function (index, file) {
var link = $('<a>')
.attr('target', '_blank')
.prop('href', file.url);
$(data.context.children()[index])
.wrap(link);
});
}).on('fileuploadfail', function (e, data) {
$.each(data.result.files, function (index, file) {
var error = $('<span/>').text(file.error);
$(data.context.children()[index])
.append('<br>')
.append(error);
});
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
});
Django backend :
in views.py :
files=request.FILES.getlist('file')
and then save it to database.
Everrthing works fine. Even image is compressed at the output but we intent to have multiple images compressed and save back to database at one hit of button.
Any sugestions are welcomed...
Thank you...
I have a drag and drop file uploader from this tutorial. The user can either click a button to choose files, or drag and drop. Either way, image previews are displayed, and then the images are uploaded when the form is submitted.
Choosing the files the old fashioned way works fine - the image previews are displayed and they are uploaded on form submission
But if I drag and drop an image, the previews are displayed, but when I submit the form they're not uploaded.
Code below:
var isAdvancedUpload = function() {
var div = document.createElement('div');
return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && 'FormData' in window && 'FileReader' in window;
}();
var $form = $('ui form');
var $fileBox = $('.box');
var $input = $fileBox.find('input[type="file"]'),
$label = $fileBox.find('label');
showFiles = function(files) {
$label.text(files.length > 1 ? ($input.attr('data-multiple-caption') || '').replace('{count}', files.length) : files[0].name);
};
if (isAdvancedUpload) {
var droppedFiles = false;
$fileBox.addClass('has-advanced-upload');
$fileBox.on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
e.preventDefault();
e.stopPropagation();
});
$fileBox.on('dragover dragenter', function() {
$fileBox.addClass('is-dragover');
});
$fileBox.on('dragleave dragend drop', function() {
$fileBox.removeClass('is-dragover');
});
$fileBox.on('drop', function(e) {
droppedFiles = e.originalEvent.dataTransfer.files;
var $imgDiv = $('.selected-images');
$.each(droppedFiles, function(index, file) {
var img = document.createElement('img');
img.onload = function() {
window.URL.revokeObjectURL($.src);
};
img.height = 100;
img.src = window.URL.createObjectURL(file);
$imgDiv.append(img);
showFiles(droppedFiles);
});
});
}
$form.on('submit', function(e) {
if ($fileBox.hasClass('is-uploading')) return false;
$fileBox.addClass('is-uploading').removeClass('is-error');
if (isAdvancedUpload) {
e.preventDefault();
var ajaxData = new FormData($form.get(0));
if (droppedFiles) {
$.each(droppedFiles, function(i, file) {
ajaxData.append($input.attr('name'), file);
});
}
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: ajaxData,
dataType: 'json',
cache: false,
contentType: false,
processData: false,
complete: function() {
$fileBox.removeClass('is-uploading');
},
success: function(data) {
$fileBox.addClass(data.success == true ? 'is-success' : 'is-error');
if (!data.success) $errorMsg.text(data.error);
},
error: function() {
console.log(data.error);
}
});
} else {
var iframeName = 'uploadiframe' + new Date().getTime();
$iframe = $('<iframe name="' + iframeName + '" style="display: none;"></iframe>');
$('body').append($iframe);
$form.attr('target', iframeName);
$iframe.one('load', function() {
var data = JSON.parse($iframe.contents().find('body').text());
$form
.removeClass('is-uploading')
.addClass(data.success == true ? 'is-success' : 'is-error')
.removeAttr('target');
if (!data.success) $errorMsg.text(data.error);
$form.removeAttr('target');
$iframe.remove();
});
};
});
$input.on('change', function(e) {
showFiles(e.target.files);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form class="ui form" action="/signup" method="post" enctype="multipart/form-data">
<!-- text inputs -->
<div class="field">
<div class="box box__input">
<input class="box__file" type="file" name="photos" id="file" data-multiple-caption="{count} files selected" multiple />
<label for="file"><strong>Choose a file</strong><span class="box__dragndrop"> or drag it here</span>.</label>
<button class="box__button" type="submit">Upload</button>
</div>
<div class="box__uploading">Uploading…</div>
<div class="box__success">Done!</div>
<div class="box__error">Error! <span></span>.</div>
</div>
<!-- text inputs -->
</form>
I was also running into this issue. Found the solution finally.
This is because when files are dropped, the drop event is only showing the file info but are not set in the file input control. So, the file input remains empty (or has the selected files if selected manually earlier).
So, when form is submitted it only submits the selected files via manual method or empty.
To set the selected files in the file input set the files property of the file input control in drop event.
$("#file").prop("files", droppedFiles);
Drag-and-drop file uploading without AJAX, synchronously in the foreground?
Thanks to the above answer, i attempted it. Somehow i had the idea that the property files is read only, hence i was not trying it.
I have a Horse model and a Photo model. I am using jQuery File Upload to resize (client side) images and save on Amazon s3 directly since I am using Heroku.
I have seen other questions similar that use carrierwave, paperclip, or that are very old. I am not sure why you would use carrierwave/paperclip, but I think based on what heroku says, I do not want to have images hitting the server potentially causing time-outs.
Heroku recommends using jQuery File Upload and shows js appending new file input with a value of the image's link (returned from amazon s3). I have this working when saving a photo separately. I now want to make it work in a nested form for Horse but js is not finding input (since it does not exist yet because it's nested I presume).
I am using Cocoon for nested forms (I am open to anything that will work better). I am not too familiar with javascript/jQuery but a far as I can tell, Cocoon 'hides' the nested element until I click to add it via the add_association.
haml view code:
= link_to_add_association 'add photo', f, :photos
html source before clicking 'add photo'
<div class='links'>
<a class="btn btn-default btn-sm add_fields" data-association-insertion-method="after" data-association="photo" data-associations="photos" data-association-insertion-template="<div class='nested-fields'>
<fieldset class="inputs"><ol><input type="file" name="horse[photos_attributes][new_photos][url]" id="horse_photos_attributes_new_photos_url" />
<input type="hidden" name="horse[photos_attributes][new_photos][_destroy]" id="horse_photos_attributes_new_photos__destroy" value="false" /><a class="remove_fields dynamic" href="#">remove photo</a>
</ol></fieldset>
</div>
" href="#">add photo</a>
How do I work with this input and how do I handle multiple file uploads as they are added correctly?
My current upload js:
$(function() {
if ($('#new_horse').length > 0) {
$.get( "/presign", function( s3params ) {
$('.direct-upload').find("input:file").each(function(i, elem) {
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.fileupload({
fileInput: fileInput,
url: "http://" + s3params.url.host,
type: 'POST',
autoUpload: true,
formData: s3params.fields,
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
disableImageResize: false,
imageQuality: 0.5,
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator && navigator.userAgent),
imageMaxWidth: 500,
imageMaxHeight: 1000,
imageOrientation: true, //auto rotates images
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, //I added this to jquery.fileupload-validate: alert('Must Be JPG GIF or PNG Image')
replaceFileInput: false,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true);
fileInput.after(barContainer);
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Pre-uploading done... Please Save or Cancel");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = 'https://' + s3params.url.host +'/' + key;
// remove first input to prevent phantom upload delay
fileInput.remove();
// create new hidden input with image url
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
var imgPreview = '<img src="' + url + '">';
form.append(input);
form.append(imgPreview);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
});
});
}, 'json');
}
});
I guess I should have looked at cocoon documentation first:
http://www.rubydoc.info/gems/cocoon#Callbacks__upon_insert_and_remove_of_items_
http://www.rubydoc.info/gems/cocoon/1.2.6
I modified my upload.js file to the following and it worked for multiple files in nested forms perfectly:
// added for file uploading
// https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails
// Get our s3params from our endpoint
$(document).on('ready page:load', function () {
$('.direct-upload')
.on('cocoon:after-insert', function(e, photo) {
console.log('inside cocoon image function');
$.get( "/presign", function( s3params ) {
$('.direct-upload').find("input:file").each(function(i, elem) {
console.log('inside nested-fields photo input form');
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.fileupload({
fileInput: fileInput,
url: "http://" + s3params.url.host,
type: 'POST',
autoUpload: true,
formData: s3params.fields,
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
disableImageResize: false,
imageQuality: 0.5,
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator && navigator.userAgent),
imageMaxWidth: 500,
imageMaxHeight: 1000,
imageOrientation: true, //auto rotates images
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, //I added this to jquery.fileupload-validate: alert('Must Be JPG GIF or PNG Image')
replaceFileInput: false,
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true);
fileInput.after(barContainer);
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Photo Uploaded");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = 'https://' + s3params.url.host +'/' + key;
// remove first input to prevent phantom upload delay
fileInput.remove();
// create new hidden input with image url
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
var imgPreview = '<img src="' + url + '">';
form.append(input);
form.append(imgPreview);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
}, 'json'); //fileupload
}); //each file
}); //presign call
}); // function cocoon
}); // page ready
I guess Google and a well documented gem can replace knowledge of JS in the short term :-) I am sure it's not at tight as it could be so please offer any improvements.
i am using this plug in for file upload
my problem is , when i click on
<input type="file" class="upload" id="imgAuthorImageUpload" accept="image/gif, image/jpeg,image/jpg,image/bmp,image/pjpeg,image/png" />
imgAuthorImageUpload - the popup will open from explore and it will let you chose the file for upload
as soon as it start to upload, i want to show that file location on page,
for example,
if i chose animal.png from d drive picture folder: then i want to display something like this
D:/Pictures/animal.png
the code i wrote like this :
$("#imgAuthorImageUpload").fileupload({
url: '/picture/DashBoard/pictureUpload.ashx',
dataType: 'json',
cache: false,
async: true,
}).on('fileuploadadd', function (e, data) {
e.preventDefault();
}).on('fileuploaddone', function (e, data) {
alert("upload done");
e.preventDefault();
}).on('fileuploadprogress', function (e, data) {
var percentVal = '0%';
var percentVal = parseInt(data.loaded / data.total * 100, 10);
$('.bar').css(
'width',
percentVal + '%'
);
$('.percent').html(percentVal + '%');
}).on('fileuploadcomplete', function (e, data) {
alert("Upload complete");
});
For security reasons, browsers don't allow this.
A good explanation is provided here: Full path from file input using jQuery
I've modified the example code provided on jQuery File Upload's Wiki My scripting works for the add callback but not the done callback. The server is getting the post correctly and returning a JSON response.
I've noticed in the source code some of the callbacks are commented out. I'm not sure if I should uncomment them or not. Or use the callback fileuploaddone But removing the comment did not work.
Not sure if i'm doing this correctly. I'd like the server to return me a JSON object describing the image I just uploaded so the next step of my form can link the image with a backbone.js model.
<form id="uploadform">
<input id="fileupload" type="file" name="imagefile" data-url="imagefiles" multiple>
<button type="#" class="btn btn-primary uploadfile" style="display: none">Upload</button>
<div id="progress">
<div class="bar" style="width: 0%;"></div>
</div>
</form>
<script>
$(function () {
$('#fileupload').fileupload({
dataType: 'json',
done: function (e, data) {
data.context = $('.uploadfile').css('display','none')
utils.addValidationSuccess('Added file: ' + data.jqXHR.name);
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .bar').css(
'width',
progress + '%'
);
},
add: function (e, data) {
console.log('added');
data.context = $('.uploadfile')
.css('display','block')
.click(function () {
utils.showAlert('Uploading','...', 'alert-warning');
data.submit();
});
}
});
});
</script>
What got things working was using jquery.ajax 's apparently native callback on submit, adjusted code shown below.
<div class="row-fluid">
<form id="uploadform">
<input id="fileupload" type="file" name="imagefile" data-url="imagefiles" multiple>
<button type="#" class="btn btn-primary uploadfile" style="display: none">Upload</button>
<div id="progress">
<div class="bar" style="width: 0%;"></div>
</div>
</form>
<script>
$(function () {
$('#fileupload').fileupload({
dataType: 'json',
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .bar').css(
'width',
progress + '%'
);
},
add: function (e, data) {
console.log('added');
data.context = $('.uploadfile')
.css('display','block')
.click(function () {
utils.showAlert('Uploading','...', 'alert-warning');
var jqXHR = data.submit()
.success(function (result, textStatus, jqXHR) {
console.log('Done');
console.log('e:' + e);
console.log('results:' + result );
console.log('results.id:' + result.id );
console.log('textStatus:' + textStatus );
console.log('jqXHR:' + jqXHR );
data.context = $('.uploadfile').css('display','none')
utils.showAlert('Success','the file uploaded successfully','alert-success');
// utils.addValidationSuccess('Added file: ' + data.jqXHR.name);
})
.error(function (jqXHR, textStatus, errorThrown){
utils.showAlert('Error','...', 'alert-error');
});
});
}
});
});
</script>
</div>
I had the same problem with this code.
$(function () {
$('#fileupload').fileupload({
dataType: 'json',
done: function (e, data) {
alert("done");
}
});
});
Just with not setting the dataType, the done callback is now executed ...
Code below just work ...
$(function () {
$('#fileupload').fileupload({
done: function (e, data) {
alert("done");
}
});
});
The server return some json.