ColdFusion 9 introduced a new Ajax UI control to allow for multiple file uploads. This little control worked well, although it did add some level of complexity to your form process. (See this blog entry where I discuss that topic.) ColdFusion 9.0.1 updates the control a bit in a couple of nice ways. Here is what I've found so far.
First, a couple of bug fixes are mentioned in the release notes. I'd say that more important one though involves the session scope and the use of URL variables. I mentioned in my previous blog entry that you needed to include your Session URL token in the url manually, like so:
<cffileupload url="uploadall.cfm?#urlEncodedFormat(session.urltoken)#" name="files" />
This is no longer the case. You can leave that off and your session is preserved automatically when the files are POSTed to your server. Also - if you want to add any additional values, you don't have to url encode the values unnecessarily. What I mean by that is - previously, if you had tried to add: ?name=ray&age=31, the & would need to be encoded. This is not an issue at all anymore. The following example works perfectly:
<cffileupload url="uploadall.cfm?name=Ray+Camden&age=37" name="files" >
I manually encoded the name value, but I could have wrapped just that portion in a urlEncodedFormat call too. There are few other bug fixes mentioned in the release notes, but that's the one I appreciate the most.
Now let's look at new feature. 9.0.1 adds a new JavaScript function, ColdFusion.FileUpload.getSelectedFiles. This is documented in the new features guide, but unfortunately the guide is a bit wrong. First, it uses the wrong case, getselectedfiles. In JavaScript, that's kinda of important. Secondly, you aren't told how to actually use the function. Luckily I guessed that it works like other built in controls - you simply pass in the name of the control. Thirdly, the docs are wrong about what is returned. It says that you get a status for each file in the control. But it mentions that a "no" status implies there is an error. That isn't true at all. The "no" status simply means it hasn't been uploaded yet. Also note that the docs mention an "uploadStatus" key. This is actually a STATUS key.
This is a great update since it now means that when we submit the form, we can check the control and see if you forgot to upload any files. Here is a simple example:
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(document).ready(function() { $("#myForm").submit(function(e) {
files = ColdFusion.FileUpload.getSelectedFiles('files');
if(files.length) {
for(var i=0; i<files.length; i++) {
if(files[i].STATUS == "No") {
alert('Your file upload is not yet complete. Please upload all files or clear any ones you do not want to upload.');
e.preventDefault();
break;
}
}
}
})
})
</script> </head>
<body> <form action="index.cfm" id="myForm" method="post">
Name: <input type="text" name="name"><br/>
Email: <input type="text" name="email"><br/>
Attachments: <cffileupload url="uploadall.cfm?name=Ray+Camden&age=37" name="files" ><br/>
<input type="submit">
</form>
</body>
</html>
<html>
I've used jQuery here to listen for the form submission. I loop over the files in the control and if any of them have a status of No (note the case!) I prevent the form from submitting. This is an excellent update as I guarantee most users won't get that they need to upload the files with a separate click.
Archived Comments
So, just to clarify, the NO status just means the user hasn't selected any files for upload? As opposed to they have selected the files, but the transfer has not yet occurred?
It is a PER file status. To detect if the user hasn't picked ANY files, you can look at the length of the array.
Make sense?
Oh wait - to be anal - you can do uploads and then clear. So to TRULY test to see if the user uploading anything, you would need to use the onUpload (I forget the exact name) API to mark it.
If you want, I can do an example of that. Logic for: a) ensure the user uploaded at least one thing versus b) if user has stuff in the queue, ensure he uploads them
That would be great Ray, we are currently facing that issue since we put that in production and testing for those things is becoming more important as our less-savvy users are now hitting it.
For those who are calling the javascript directly, here are the parameters for the ColdFusion.FileUpload.create.
ColdFusion.FileUpload.create=function
(_60f,//uploadDivId
_610,//url_withoutQuery
_611,//url_queryString
_612,//url_CF_cookie
_613,//addButtonLabel
_614,//ClearButtonLabel
_615,//UploadButtonLabel
_616,//DeleteButtonLabel
_617,//title
_618,//maxFileSelect
_619,//UploadSize
_61a,//onCompleteHandler
_61b,//onUploadCompleteHandler
_61c,//onErrorHandler
_61d,//width
_61e,//height
_61f,//bgcolor
_620,//selectcolor
_621,//rollovercolor
_622,//textcolor
_623,//titletextcolor
_624,//headercolor
_625,//titletextalign
_626,//fileFilter
_627,//progressbar
_628,//iconpath
_629,//disableUploadButton
_62a,//stopOnError
_62b,//wmode
_62c //align
)
Good to hear that sessions are now preserved automatically.
Have you had any luck getting that control to work in AJAX? Like loading it using jQuery's ajax library. It seems to be loading so much stuff on init that I couldn't quite get it to work right...no matter the datatype.
Brian pointed out the code above, but I don't believe there is any documented way to create a file uploader.
JF,
We use ExtJS (now Sencha) as our Ajax framework. Calling the file uploader via javascript prevents coldfusion from loading the style sheets and other conflicting libraries. I will post the minimum things needed to get the file uploader to work. I tried posting the entire javascript, but I think there is a comment size limit.
It looks like I cannot add code or script calls to the comments section. Is there a way to include code examples?
Brian - please use pastebin. Blog comments really aren't good for code samples. :)
ok, I posted the javascript needed on the forums. This should be what you need to include the file uploader in an Ajax framework.
http://www.coldfusionjedi.c...
Is there a reason why cffileupload will not work under ssl? I have some test code that works fine on my server on a non-ssl domain, but fails (on the same server) under a SSL domain. Using Charles to sniff the traffic, it seems the server immediately refuses the request coming from the flash app when I try to upload. Any suggestions?
Sorry, no idea on that one. I can't see why it would block SSL. Worse comes to worse, maybe try Uploadify? It's the solution I normally use for file uploads.
If you have a moment, I was wondering if you can confirm that the multi-file uploader doesn't work with CFLOGIN after the 9.0.1 update. In my test code, I have found that the .cfm page where it uploads the files triggers the cflogin block in my application.cfc code (i.e. it doesn't detect the cflogin struct). It DOES however, and strangely, have access to the Session information.
I can work around this in the application.cfc by letting requests for the upload page through and then checking for a flag in the Session struct, but I would rather it work as expected. Lol. Anyway, I know that you don't use CFLOGIN generally, but I am really going crazy over this issue.
What are you using for loginStorage in your Application.cfc file?
Aha! I have it set to "cookie". I haven't tried it set to "session" for this test (I think I stopped doing that because of some past security issue...can't remember.)
I will try it with session and see if works. Thanks!
Let me know. That should be it.
CFLOGIN suffered more than one security issue, but as of the latest 8.X it should be locked down. Certainly in 9 it is.
It's always the little things! Setting loginstorage="session" *did* allow the cffileupload to work behind cflogin as expected (and hoped).
Thanks again! Maybe this will at least help anyone else avoid this gotcha when trying to add the multi-file uploader to an already existing application that uses cflogin.