ColdFusion 9 added a snazzy little Ajax-based (well, Flash based to be truthful) multi-file uploader. Just in case you haven't actually seen it, here is a quick snap shot of what it looks like:
I've done a few blog posts on this topic already. Today a reader sent in an interesting question. While the control provides a way to limit the total file size of uploads (using the maxuploadsize attribute), there is no direct way to limit the size of individual file uploads. This blog entry will show one way that can be accomplished. I'll be using jQuery for my solution but please note that this is not a requirement.
Ok, so the first problem we run into is that there is no support for noticing when a file is added to the queue. If there was, we could listen for that and simply throw an error then. The next problem is that there is no support for a "pre"-upload event. You get support for an upload complete event - but not one for right before the uploads begin. Luckily we have a way to work around this. We're going to disable the upload button and use our own logic to fire off the uploads. I'll show the entire template below and then walk you through what it does.
<html> <head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#uploadBtn").click(function() {
//get all the files
var files = ColdFusion.FileUpload.getSelectedFiles('myfiles');
if(files.length == 0) {
alert("You didn't pick anything to upload!");
return;
}
var oneTooBig = false;
for(var i=0; i<files.length; i++) {
if(files[i].SIZE > 40000) {
oneTooBig = true;
alert("The file, "+files[i].FILENAME +" is too big. It must be removed.");
}
} if(!oneTooBig) ColdFusion.FileUpload.startUpload('myfiles');
});
});
</script>
</head> <body> <cffileupload name="myfiles" maxuploadsize="10" hideuploadbutton="true">
<br><br>
<input type="button" id="uploadBtn" value="Upload Mah Filez!"> </body>
</html>
First - notice how in the cffileupload control I've used the hideuploadbutton attribute. As you can guess, this removes the button you would normally use to upload all the files. I've added my own button, uploadBtn, that will be used instead.
Now let's look at the JavaScript. When the upload button is clicked, I begin by using the ColdFusion Ajax API call, getSelectedFiles, to get an array of files in the control. Once I have that, it's rather trivial. I loop over each and if the file size is too big (I used 40K as an arbitrary limit), then I flag it and alert it to the user. If no file was too big I can then fire off the upload request, again using the document Ajax API call startUpload().
That's it. You can see here in this screen shot how the button was removed.
Archived Comments
This is great Ray. Thanks! I had wondered about and been asked about that myself.
I finally got a chance to take a better look at this and when I try to "Upload Mah Filez!" nothing happens (using the code as shown).
I've only ever used cffileupload once and it was pretty much standard use via the docs, so it's entirely possible I missed the plot entirely!!
As I said, I didn't change anything, was just trying to get started with the example. Any thoughts on what I might have done wrong?
Right after
$("#uploadBtn").click(function() {
add
console.log("CLICK HANDLER RUN");
This will only work if you have Firebug, or Google Chrome (and ensure the JavaScript console is open).
Works perfectly in Chrome and Firefox after adding that line!
I apologize for the double post, I just wanted to correct myself a little and expand on that last statement...
The page works fine with or without the extra line in either Firefox or Chrome (although I did get a 'console' is undefined error in Firefox the first time I tried it before adding the line - Been fine since, even with it removed again) and does log the click under both when added.
The page does not work for me in Safari 5 (Mac).
Hope that clears up any confusion that I may have caused.
It does clear things up a bit - enough for me to test on my Mac.
I just tried it and it works fine. Let's try this. Keep the console message in and open up Safari's JS console. Also add a console.log("doc ready") after the document ready line. That should run on startup, and the other msg should run when you click. Please confirm that.
Looks like there is an error:
TypeError: Result of expression '_650.getSelectedFileArray' [undefined] is not a function. ... cffileupload_swf.js:245
Didn't see this before, but it doesn't mean much to me unfortunately.
So if you do a console.log before and after ColdFusion.FileUpload.getSelectedFiles('myfiles')
you can see it breaks right there, right?
That is correct, yes.
Hmm. Unfortunately that's Adobe shipped code, I can't help with that. It is odd that I don't get it with my Safari though. Is your code online where I can hit it?
I don't have a copy anywhere online right now, no.
It's just a word for word copy of your demo right now though.
The reason I want to see is that maybe something on your server is wrong. If you use FIrebug, or Google net tools, or Safar's, but I'm not sure where - maybe you see a JS library not being loaded right.
Sorry to pester you again with this, but I was able to get an example online, with the console commands added.
Doesn't work in Safari, Chrome or Firefox at this url.
http://www.cfdevshack.com/t...
Works locally as is. Debugging is not turned on.
I know this sounds crazy, but I can't get a basic cffileupload to display. Accessing the page from the server while inside the firewall and everything is beautiful. Using the same version of Firefox from outside the firewall, and the area where the control should be is blank. The source code view shows the exact same code.
any thoughts???
Something on your network is blocking /CFIDE files. Check there.
@Daren: Are you using 901? This API is 901 only I believe.
901 would likely explain my issue. I will have to check the live version.
I know the standard cffileupload works in it's place but If this version only works under 901 though, that is probably the cause of my problem. Thanks again.
Will check the firewall to see what is going on! Works internal and in from the DMZ, just not from external. BTW tried to load the 9.0.1 update and it crashed my installation last week. Had to recover from an virtual server image.