I am trying to limit the file extensions that can uploaded through plupload.
because the filters do not work properly with the HTML5 runtime I cannot use them. hence I have the below code binded to the FilesAdded
event
var extensionArray = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];
uploader.bind('FilesAdded', function (up, files) {
var invalid = 0;
for (var i in files) {
var extension = files[i].name
.substr((files[i].name.lastIndexOf('.') + 1))
.toLowerCase();
if (extension == '' || -1 === $.inArray(extension, extensionArray)) {
uploader.splice(i, 1); //also tried uploader.removeFile(files[i])
invalid++;
continue;
}
//dom manipulation to add file occurs here
}
});
But, whilst this is stopping the dom manipulation occuring for any invalid files, it does not seem to be actually removing the item from the queue as when I initiate the upload they are all sent across!
This is happening on both the HTML5 and the Flash Runtime. I have not tested the others yet.
Binding to the FilesRemoved
event, it is never triggered! but inserting console.log('Invalid files detected');
just before uploader.splice(...
it is outputted to the console, so that line is getting called.
Short Version: You need to bind to the filesAdded
event after calling the init()
function.
my first step for debugging was to grab the uncompressed version off github18 Nov 2012. Once I had that I could trace the issue.
So the primary issue seemed to be that the call to removeFile()
was never getting called, but why?
removeFile()
was defined as:
removeFile: function (file) {
var i;
for (i = files.length - 1; i >= 0; i--) {
if (files[i].id === file.id) {
return this.splice(i, 1)[0];
}
}
}
Ok, pretty simple, this loops through the files array and if there is a file that has the matching ID then we call the splice function.
So, what does splice look like?
splice()
was defined as:
splice:function (start, length) {
var removed;
// Splice and trigger events
removed = files.splice(start === undef ? 0 : start, length === undef ? files.length : length);
this.trigger("FilesRemoved", removed);
this.trigger("QueueChanged");
return removed;
}
Right, so that is where the FilesRemoved
event should have been triggered, so why wasn't it?
Back in the removeFile()
function, as noted, it only calls splice if a matching id is found.
So, the next step was to find out if the removeFile function was even being called.
Inserting console.log('removeFile called', files);
as the first line gave us the output: removeFile called []
Hmmm, an empty array!
Ok then, Looks like us binding to the FilesAdded
event is stopping it's usual behavior, no problem. let's just add uploader.files.push(file)
to our FilesAdded
binding. and lo and behold. when we click start, only the correct files are sent.
It's working... but not quite.
I had a couple of extra bindings in there, just for debugging purposes, one of those was on QueueChanged
. this logged the amount of files in the queue each time there was a change.
What I noticed was that the number of files in the queue was not actually reflecting that there was files removed from the queue.
So, a quick console.log(uploader.files.length)
and this confirmed that there was something else going on here.
Next step was to look at what the default action was for adding files.
Looking I noticed that the developers decided to bind to the event as well, doing this inside the init function. An odd choice looking at it from my perspective. But that's their choice.
So, looking inside their binding they also had a files.push(file)
meaning that we were getting all files + duplicates of the correct files in the array.
Noting that the binding was happening in the init()
, function, I removed the uploader.files.push(file)
from my binding, moved the init()
call to before my FilesAdded
binding. and now everything works well.