I'm trying to use the jQuery File Uploader, but I'm having trouble. I've downloaded the plugin from here:
https://github.com/blueimp/jQuery-File-Upload
and been through the documentation. I've got the plugin working on my site, within its own sub directory, but now I want to use the functionality on my own page and I'm having a problem.
When i navigate to the plugin pages in the subdirectory everthing works normally, but when I copy elements of the code and deploy it to my own page something is going wrong. Specifically, on the plugin page the thumbnails all show OK, even on my own server - however, when I use it on my page the thumbs arent uploading properly.
I've noticed that when the page from the plugin loads, there is GET call to the /server/php folder, which contains the file that holds the classes for the plugin, but on my page the same call doesnt run.
I have the pages online in case anyone can help:
The one that is working is here:
http://54.187.7.151/jQfileUpload/index.html
and the one that isnt is here:
http://54.187.7.151/div.php
In terms of file structure, I'm calling the handler script within the plugin from jQuery (/jQfileUpload/server/php) from 'div.php' and just (/server/php) from /jQfileUpload/index.html, since it sits in the same folder.
This has been killing me all afternoon!! Can anyone help?
JQuery for http://54.187.7.151/jQfileUpload/index.html (the only difference between this and div.php is the path to the handler script :
$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
var url = window.location.hostname === 'blueimp.github.io' ?
'//jquery-file-upload.appspot.com/' : 'server/php/',
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');
});
Related
I have a dropzone script which uploads file to a certain directory. I did read a lot of the documentation already but still I'm stuck. I have this JS:
$(document).ready(function () {
Dropzone.autoDiscover = false;
var selectorElement = '.fileUploader';
var selector = $(selectorElement);
selector.addClass('dropzone');
selector.dropzone({
dictInvalidFileType: 'Kan bestand niet uploaden: ongeldige extensie.',
dictFileTooBig: 'Kan bestand niet uploaden: bestand te groot.',
dictResponseError: 'SERVER ERROR',
paramName: 'file[]', // The name that will be used to transfer the file
maxFilesize: 1000, // MB
url: 'ajax/uploadFile.php',
addRemoveLinks: true,
enqueueForUpload: true,
uploadMultiple: true,
sending: function (file, xhr, formdata) {
formdata.append('uploadPath', $(this)[0].element.dataset.uploadpath);
$(this).css({width: $(this)[0].element.getAttribute('width'), height: $(this)[0].element.getAttribute('height')});
},
init: function ()
{
var myDropzone = this;
this.on('maxfilesexceeded', function (file) {
this.removeFile(file);
});
this.on('removedfile', function (file) {
if (file.previewTemplate.children[6])
{
var filePath = this.element.dataset.uploadpath + file.previewTemplate.children[6].value;
$.post('ajax/deleteFile.php', {file: filePath}, function (response) {
CMSnotification(response.message, response.type);
}, 'JSON');
}
});
this.on('successmultiple', function (files, response) {
var responseJSON = JSON.parse(response);
CMSnotification(responseJSON.melding, responseJSON.type);
if (responseJSON.type === 'foutmelding')
{
for (var i = 0; i < files.length; i++)
{
var previewTemplate = $(files[i].previewTemplate);
previewTemplate.children('.dz-success-mark').css('display', 'none');
previewTemplate.children('.dz-error-mark').css('display', 'block');
previewTemplate.removeClass('dz-success').addClass('dz-error');
}
}
for (var i = 0; i < files.length; i++)
{
var previewTemplate = $(files[i].previewTemplate);
if (!responseJSON.files[i])
{
previewTemplate.children('.dz-success-mark').css('display', 'none');
previewTemplate.children('.dz-error-mark').css('display', 'block');
previewTemplate.removeClass('dz-success').addClass('dz-error');
}
else
{
previewTemplate.append('<input type="hidden" name="fileNames[]" value="' + responseJSON.fileNames[i] + '">');
previewTemplate.append('<input type="hidden" name="extensions[]" value="' + responseJSON.extensions[i] + '">');
}
}
});
},
accept: function (file, done) {
var extension = file.name.split('.').pop();
extension = extension.toLowerCase();
if ($.inArray(extension, window.allowedFileDropzoneExtensions) > -1) {
done();
}
else {
done('Bestands extensie niet toegestaan.');
}
}
});
});
The first problem is, I include this file once and still it gives the error dropzone already attached. But the biggest problem is:
The dropzone is pretty inconsistent. For 3 files, it calls 3 request files. For 8 files, it can call 4 request files. But it should just call 1. The problem is, if I allow the user to give a callback as parameter in the function and call it in the success event of the upload, it will call that callback multiple times (but it should just call it once).
The first problem is because you have the statement Dropzone.autoDiscover = false inside the .ready() function, and this causes to trigger it to late. Move this statement outside the .ready() function.
Dropzone.autoDiscover = false;
$(document).ready(function () {
.........
})
The second is due to the way dropzone works, by default the option autoProcessQueue is set to true, and dropzone uploads the files immediately after they are added. I think there is no guarantee of how many files will upload at once, but I think that by default will never upload more than two.
A solution is to manually trigger the upload of the files, to do this you need to set autoProcessQueue to false, just to mention an example you can use a button that triggers the upload, inside the init option add an event listener for the button that triggers the processQueue() method. Here an example of this solution:
html:
<button type="button" id="submit-all">Submit All</button>
js:
selector.dropzone({
autoProcessQueue: false,
uploadMultiple: true,
init: function () {
var submitButton = document.querySelector("#submit-all");
myDropzone = this;
submitButton.addEventListener("click", function () {
myDropzone.processQueue();
});
}
})
I just included the relevant part for this to work, you can add this to your existing configuration. This will also solve your problem for the successmultiple event.
I'm struggling with the plugin JQuery-File-upload.
I would like to divide the upload process in two steps.
Step1 - when a file is selected in the input[type=file], I would
like to test its type and its size. The only accepted files should be
image files with a size < 4MB.
If the file does not match with these constraints a popup is displayed with an error message.
If the file is OK I display the name of the file in the input[type=text]
Step2 - when the user click on the button "OK", the upload of the
file start
I have the following code
$('#file-img').fileupload({
dataType: 'json',
autoUpload: false,
formData: {type: 'businessPicture'},
add: function (e, data) {
var uploadErrors = [];
var acceptFileTypes = /^image\/(gif|jpe?g|png)$/i;
if(data.originalFiles[0]['type'].length && !acceptFileTypes.test(data.originalFiles[0]['type'])) {
uploadErrors.push('Not an accepted file type');
}
if(data.originalFiles[0]['size'].length && data.originalFiles[0]['size'] > 4000000) {
uploadErrors.push('File size is too big');
}
if(uploadErrors.length > 0) {
alert(uploadErrors.join("\n"));
} else {
$.each(data.files, function (index, file) {
$("#txt-file-img").val(file.name);
});
//I COMMENT THIS LINE because if I do not, the upload start here.
//data.submit();
}
},
done: function (e, data) {
$("#output").html('<p class="valid">SUCCESS!</p>');
$.each(data.result.files, function (index, file) {
$("#preview-picture").css("max-width","160px");
$("#preview-picture").css("max-height","150px");
$("#preview-picture").attr("src",file.url+'#'+ new Date().getTime());
});
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#upload-progress .bar').css(
'width',
progress + '%'
).text(
progress + '%'
);
},
fail: function (e, data) {
$("#output").html('<p class="error">FAIL!</p>');
}
});
});
I don't understand most of the example provided on the Plugin website.
With the code above, the control (size & type) are OK but I don't know how to start the upload only after clicking on the button.
According to you what is the best way to manage this behaviour?
Thanks a lot
OK it's pretty easy. I just have to bind the click event on the button with the action data.submit directly under the event add of the instance $('#file-img').fileupload().
$('#file-img').fileupload({
dataType: 'json',
autoUpload: false,
formData: {type: 'businessPicture'},
add: function (e, data) {
var uploadErrors = [];
var acceptFileTypes = /^image\/(gif|jpe?g|png)$/i;
if(data.originalFiles[0]['type'].length && !acceptFileTypes.test(data.originalFiles[0]['type'])) {
uploadErrors.push('Not an accepted file type');
}
if(data.originalFiles[0]['size'].length && data.originalFiles[0]['size'] > 4000000) {
uploadErrors.push('File size is too big');
}
if(uploadErrors.length > 0) {
alert(uploadErrors.join("\n"));
} else {
$.each(data.files, function (index, file) {
$("#txt-file-img").val(file.name);
});
$("#btn_add_valid").on('click',function () {
data.submit();
});
}
},
//The rest of the function....
I have this strange issue and I've tried several solutions (even implementing the same as the Basic Plus demo on their website). I can upload files just fine, single or multiple. They upload on a click of the individual item, or a "Upload All" button. The problem is trying to add additional files before or after uploading. The file upload plugin will not even detect that these files are changing in the file input, so it never fires the "fileuploadadd" event, and requires me to refresh the page in order to upload more files. I'm wondering whether the fileupload change event is being lost somewhere, but I cannot for the life of me figure out where.
Also, does the blueimp file upload plugin require a specific return format of JSON? At the minute, I'm just returning "{\"status\":\"success\"} if the uploads are a success, and a similar error message. EDIT: Changing the response format to examples shown by blueimp had no effect.
Here's some code for the uploader I'm using. Note that I'm currently using ASP.NET and jQuery 2.0.3, and jQuery UI 1.9.2.
function initFileUploader() {
//initProgressBars();
$(upload_progressbar_title).css('display', 'none');
$(upload_progressbar).css('display', 'none');
$(upload_upload).on('click', function () {
$(upload_progressbar).css('display', 'block');
$(upload_progressbar_title).css('display', 'block');
$('.uploadbtn').click();
});
$(upload_browse).on('click', function () {
$(upload_file).click();
return false;
});
$.guid = 0;
console.log('initialising file upload');
var uploadButton = $('<input type="button" id="button" />')
.addClass('button tiny').addClass('uploadbtn')
.prop('disabled', true)
.val('Processing...');
var uploadCon = $('<div class="small-4 medium-6 large-6 columns progresscontainer" />')
.append('<div class="progressbar" />')
.append('<label class="progressbarlabel">Not uploading</label>');
uploadCon.append($(uploadButton).on('click', function () {
var $this = $(this),
data = $this.parent().data();
$this
.off('click')
.val('Abort')
.on('click', function () {
$this.remove();
data.abort();
});
data.submit().always(function () {
$this.remove();
}).success(function (result, textStatus, jqXHR) { console.log("Result: " + result + " - TextStatus " + textStatus); })
.error(function (jqXHR, textStatus, errorThrown) { console.log("Error: " + errorThrown + " - TextStatus " + textStatus); })
.complete(function (result, textStatus, jqXHR) { console.log("Result: " + result + " - TextStatus " + textStatus); });
}));
$(upload_file).fileupload({
dataType: 'json',
autoUpload: false,
acceptFileTypes: /(\.|\/)(pdf|jpe?g|png|doc|docx)$/i,
maxFileSize: 5000000, // 5 MB
}).on('fileuploadadd', function (e, data) {
var uniqueId = $.guid++;
data.context = $('<div id="div_upload_dcon_' + uniqueId +'" class="row"/>').appendTo(upload_filescon);
$.each(data.files, function (index, file) {
file.uniqueId = uniqueId;
var node = $('<div id="div_fname" class="small-6 medium-4 large-4 columns"/>')
.append($('<span/>').text(file.name));
if (!index) {
data.url = baseUrl + 'PostUploadFile?fileName=' + data.files[index].name + '&refId=' + ClientRefId + '&upbyid=' + ClientUserId + '&ticketId=' + globalTicketId;
var contentNode = (uploadCon.clone(true).data(data));
}
node.appendTo(data.context);
$(contentNode).appendTo(data.context);
$(upload_file).on('change', function () {
alert('changing fileinput');
});
});
}).on('fileuploadstart', function (e, data) {
initProgressBars();
}).on('fileuploadchange', function (e, data) {
alert('changing');
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index,
file = data.files[index],
node = $(data.context.children()[index]);
if (file.error) {
console.log(file.error));
}
if (index + 1 === data.files.length) {
$('.uploadbtn').val('Upload').prop('disabled', !!data.files.error);
}
}).on('fileuploadprogress', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#div_upload_dcon_' + data.files[0].uniqueId).progressbar('value', progress);
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$(upload_progressbar).progressbar('value', progress);
}).on('fileuploaddone', function (e, data) {
getTicketContent(globalTicketId);
}).on('fileuploadstop', function (e, data) {
$(upload_file).val('');
}).on('fileuploadfail', function (e, data) {
$.each(data.files, function (index, file) {
var error = $('<span class="text-danger"/>').text('File upload failed.');
$(data.context.children()[index])
.append('<br>')
.append(error);
});
});
}
Well, after a night's sleep and more thinking about it, I specified this option
replaceFileInput: false,
during the file upload initialisation. And guess what, it works as intended now. I'm guessing that the file input was being lost because the fileupload clones the control by default after an upload or change.
Thanks for any consideration anyone may have given this, I hope it comes in handy for someone else in the future.
It's been two years since the original answer, but I just figured this out for my own case (:
If you use replaceFileInput: false, the code will not work in IE9, which does not support the newer file upload APIs. According to the documentation the fallback support for this browser depends on an "iframe transport" that requires the file input element be replaced each time. Reading that was the big clue for me.
What's really killing you is this:
$(upload_browse).on('click', function () {
$(upload_file).click();
return false;
});
You are assuming that upload_file is still the same element, but it's been replaced with a clone. You're firing a click event on the old file input element. It exists, so you get the system browse dialog, but it's not hooked up to any plumbing.
So the correct solution with full IE9 support is to use "find" to locate upload_file anew each time this click handler is fired. You didn't include your code for setting upload_file, so I don't know what the correct selector would be in your case, but it would look something like this:
$(upload_browse).on('click', function () {
// You should use a more specific selector, better yet use
// find() to locate it inside some div you know is "in scope" so
// you don't fire every file input on the page. Just an example
$('input[type=file]').click();
return false;
});
I am using jQueryUI, and jQuery BlueImp File Uploader. Using the uploader, I would like to create drag and droppable UI objects with jQuery UI.
In order to do this however, I need to append a <li> and </li> tag to the front and back of the file that is displayed. For example, in the below script I am using the uploader to display thumbnails of each of the images uploaded.
How can I prepend li and append /li to each image that is being displayed?
<script>
/*jslint unparam: true, regexp: true */
/*global window, $ */
$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
var url = window.location.hostname === '' ?
'' : 'server/php/',
uploadButton = $('<button/>')
// .addClass('btn')
.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: true,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png|mp4)$/i,
maxFileSize: 50000000, // 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('')
// .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('')
.prepend(file.preview);
}
if (file.error) {
node
.append('<br>')
.append(file.error);
}
if (index + 1 === data.files.length) {
data.context.find('button')
// .text('Upload2')
.prop('disabled', !!data.files.error);
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#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');
});
</script>
I have a custom file upload implementation for the blueimp/jQuery file upload control. It works great except when I choose multiple files and one of them exceeds the maximum length, it still attempts to upload the out of bounds file (even though I don't call data.submit() for that particular file).
I have verified the progress event doesn't fire for the large (and unsubmitted) file, but the server ultimately reports a 404.13 (The request filtering module is configured to deny a request that exceeds the request content length), and none of the other files that were actually submitted get uploaded.
How can I change the way I use the jQuery file upload control to upload the valid files, but ignore the large file?
Here is my code...it manipulates a model that is leveraged by knockout to display UI elements, so you won't see any UI manipulation in the code below.
$('#fileupload').fileupload({
dataType: 'json',
url: '/Handlers/UploadHandler.ashx',
progress: function (e, data) {
console.log(data.context);
var progress = parseInt(data.loaded / data.total * 100, 10);
var file = fileUploadDataModel.files()[data.context];
file.percentComplete(progress);
},
add: function (e, data) {
$.each(data.files, function (index, file) {
var fileModel = new FileModel(file.name, file.size);
fileUploadDataModel.files.push(fileModel);
data.context = fileUploadDataModel.files().length - 1;
if (file.size > opts.maxFileSize) {
fileModel.errorMessage('{0} ({1}) exceeds maximum size -- rejected'.format(file.name, friendlyBytes(file.size)));
fileModel.percentComplete(0);
}
else data.submit();
});
},
done: function (e, data) {
var file = fileUploadDataModel.files()[data.context];
file.percentComplete(100);
},
singleFileUploads: false,
});
I was able to get this to work by marking the files that were invalid, removing them from the data.files array and then submitting the rest. Here is the fixed code...
$('#fileupload').fileupload({
dataType: 'json',
url: '/Handlers/UploadHandler.ashx',
progress: function (e, data) {
console.log(data.context);
var progress = parseInt(data.loaded / data.total * 100, 10);
var file = fileUploadDataModel.files()[data.context];
file.percentComplete(progress);
},
add: function (e, data) {
var itemsToRemove = [];
$.each(data.files, function (index, file) {
var fileModel = new FileModel(file.name, file.size);
fileUploadDataModel.files.push(fileModel);
fileModel.sourceIndex = fileUploadDataModel.files().length - 1;
file.fileModel = fileModel;
if (file.size > opts.maxFileSize) {
fileModel.errorMessage('{0} ({1}) exceeds maximum size -- rejected'.format(file.name, friendlyBytes(file.size)));
fileModel.percentComplete(0);
itemsToRemove.push(index);
}
});
itemsToRemove = itemsToRemove.reverse();
for (index in itemsToRemove)
data.files.splice(itemsToRemove[index], 1);
$.each(data.files, function (index, file) {
data.context = file.fileModel.sourceIndex;
data.submit();
});
},
done: function (e, data) {
var file = fileUploadDataModel.files()[data.context];
file.percentComplete(100);
},
singleFileUploads: false,
});