File upload explained and expanded
128 comments Posted by: LauraAs we showed in our post File Upload with ColdFusion Flash Forms, file upload is now possible with Flash 8. I introduced it with a custom tag that nicely wraps the functionality of the file upload. It is quite flexible, -hopefully- easy to use, and I believe I’ll use it whenever I need to add a file field in my flash forms. But for those of you who are curious to know how it works, or need additional functionality (which I may add to the tag in the future), this is a walk through the main functions that make it work.
p>The swf file you will find in the zip contains the libraries that make file I/O possible. In order to have those available in our flash form, we load it in a textarea. Why not use a cfformitem type=”html”? Because at the moment, that type does not have an id attribute, so we cannot reference it later.Just so that we don’t have to escape the quotes, make a variable with the swf code:
<cfset swf = '<p><img id="upload" hspace="0" vspace="0" src="fileUpload.swf"></p>' />
<cftextarea name="textArea" disabled="true" visible="false" width="0" bind="{(textArea.html = true) ? '#swf#' : ''}" height="0"></cftextarea>
The browse button will have the following:
//a reference to the swf
var uploadSwf = textArea.label.upload;
//make an empty object that will be the upload listener
var uploadListener = {};
//we'll add uploadListener to be a listener of the file upload events triggered by our library
uploadSwf.addListener(uploadListener);
//we are then ready to trigger the browse action. We can pass it some parameters such as the types of file we accept, and the description of these file types
uploadSwf.browse([{description: "Image Files", extension: "*.jpg;*.gif;*.png;"}]);
Our listener object can implement any of these functions, which will be called by the library after the browse has been triggered
- onSelect(file)
- onComplete()
- onProgress (fileRef, bytesLoaded, bytesTotal)
- onSecurityError(fileRef,errorString)
- onIOError(fileRef)
- onHTTPError(fileRef,errorNumber)
- onCancel()
this function will be called when a file has been selected by the user.
uploadListener.onSelect = function(selectedFile){}
Inside this function, it is our opportunity to check for file size or any other property:
- selectedFile.name
- selectedFile.size (in bytes)
- selectedFile.type
- selectedFile.creationDate
- selectedFile.modificationDate
We can also use these to show the selected file name in a text input.
onComplete will be called when the file has been uploaded
uploadListener.onComplete = function(){}
and the onProgress function is called while the file is uploaded to report progress
uploadListener.onProgress = function(fileRef, bytesLoaded, bytesTotal){}
We use that to make the progress bar and to show progress information.
Once we are set up and a file has been selected, we can call upload (most likely from an “upload” button):
uploadSwf.upload("upload.cfm");
We could append some variables to use in the action page.
uploadSwf.upload("upload.cfm?fileId=1");
We could also add a “Cancel” button with the following code to cancel the upload:
uploadSwf.cancel();
A live example
Download the source
128 Comments so far
Write yoursWhenever i upload a file, I am able to hit upload again and it will reupload the file again, and I can keep hitting the upload button over and over, and keep uploading the same file.
I managed to reset the text under the
attributes.progressInfo>uploadListener.onComplete = function()
with:
fileNameField.text= "";
but not the actual file value. I tried using a normal reset function, but it seems to not work.
Tried setting the selectedFile.name=""; as well.
any suggestions?
You can disable the upload button if you want to force them to choose another file before they upload again. I did that in the post: http://www.asfusion.com/blog/entry/showing-an-image-after-upload
Seth,
No, Flash 8 does not expose the full path for security reasons.
Dyllan,
No, as of now, only GET data can be sent to the action page.
I had this problem when I was using static variables anywhere in the chain. Are you binding to static vars anywhere?
I have been unsuccessful in reading the GET data I send along with this. Would you be kind enough to post an example or give me some direction? Thanks!
The only data that we can send is by query string:
uploadSwf.upload("upload.cfm?fileId=1");
In that case, we would receive a variable called url.fileId with value 1 in the action page (upload.cfm)
You can see an example of that in the post
http://www.asfusion.com/blog/entry/showing-an-image-after-upload
where I am sending the file name I want for the image.
Hope that helps
I did the following:
uploadListener.onComplete = function()
{
<cfif attributes.uploadButton>uploadBtn.enabled = false;</cfif>
}
What can I add to disable the browse and display a close window button or automatically close the window?
Thanks
JC
You would get a 404 if the upload action does not exist. In the post example, the page that receives the file and handles the upload is called "upload.cfm" and it's located in the same directory as the cfform. You should change it according to your own page name and directory structure.
I have done that. And after the file attempts to upload and the status bar says 100% complete, I get an error right under the status bar that says "HTTP 404 Error". I have double checked my file locations and naming and everything appears to be correct. Could there by any other answers?
I tried moving both the upload.cfm and the flashupload.swf into the folder where my index page is at rather than moving things around like I tried to do. This took care of the 404 error, but now I get an HTTP 500 Error. Any clue on why I would get the 500 now?
As for the 404 error, do you think moving the files solved that problem? Where in the code would one have to change in order to point to a different folder?
Thanks,
Justin
404 means file not found, therefore moving your files definitely solved your problem. If you do not want to have them in the same directory, make sure you put the correct path to the upload file (I would even recommend to use absolute path, /mydir/upload.cfm)
Regarding the 500 error, it is difficult for me to know what your problem is, but as some other person suggested, make a test.cfm file with the following code (change upload.cfm in the action attribute if your upload action page is named differently):
<form action="upload.cfm" method="post" enctype="multipart/form-data"><input type="file" name="Filedata"><input type="submit" name="Upload" value="Upload">
</form>
Run it, try to upload something and see what happens. For the most part, that is what Flash is trying to do, so you will see the same error Flash is getting and it will help you understand the problem.
Hope that helps
any thoughts?
-Steven
They have an example of what you are talking about on the entry where the photograph is shown after upload.
http://www.asfusion.com/blog/entry/showing-an-image-after-upload
That is a bug in the player. At least in our experience, it only happens in Firefox, not in IE.
We have logged it during the beta but it has obviously not been fixed in the final release. I've tried appending the necessary variables (cftoken/cfid or jsessionid) but it passes "some" wrong variables that overwrite the query string. The behavior is quite strange.
I think the best is that every person that experiences it reports it to Macromedia and maybe they will see a need to fix it.
James,
Yes, add the value you need into a hidden field
<cfinput type="hidden" name="duid" value="#queryname.duid#" />
what's important is that in order to access that hidden field you need to write theNameOfYourForm.duid
uploadSwf.upload("upload-image-action.cfm?id=" + theNameOfYourForm.duid + ".jpg");
James
Ps. Sorry to bother you so much on these snippits.
Great stuff here i keep coming back on a daily basis there is a lot to learn. My question: Is it possible to upload multiple files instead of just one?
thanks
Yes is that possible but not in this example. We are planing to make an example when we get a chance.
I'll give it a shot with IE. Thanks again.
Thanks for your vivid response. Indeed its possible to upload multiple files. MM help reference is doing a good job here. a search for filereferenceList did the job. This is cool stuff guys.
I finally got back to working on the Flash 8 upload. I tried your suggestion about trying the upload as a ColdFusion form upload, not using Flash, to see if I get the same HTTP 500 Error. I do not get that error, in fact, it uploads completely successfully.
Would you or someone out there give me some idea why I would get the HHTP 500 Error with the flash form upload but not with the normal CFML form upload?
Thanks,
Justin
Also, just curious, I have up to four images that will be uploaded that will go along with a particular article. Any ideas on how I can make sure those images are related to that particular article? This is especially a problem right now for me if I have to load one image at a time.
Thanks,
Justin
local HD to a server.
The kind that is in
http://www.asfusion.com/blog/examples/item/file-upload-explained
When I had downloaded the source files,they are not working for me.I don't know where the problem is.I really know nothing about Cold Fusion.
Can you help me please..?Why the "fileUpload.swf" is not showing anything to me?
the source files should work as is. I would say that you may not have Flash Player 8. Also, does any other flash form work for you?
fileUpload.swf does not show anything because it only contains an ActionScript library to use in the flash form.
This way, the browser believes it is a new image address every time and doesn't show the old image.
You can only send variables via query string. Otherwise, submit the form for the other fields.
In the browse button, you have it only lookign for image files, that is edited in the <cfsavecontent variable="browseScript"> function.
How could I do the same thing outside of this example? I am trying to have that same function in a regular form, and I believe it is possible. Yet I cant find any info on how to make the browse dialog only show specified extensions, rather than all files.
Any idea?
as I was trying to add some actions when my upload is completed, I found a weird behavior...
I want to add a row to a datagrid when a file is uploaded. So i have something like that:
uploadListener.onComplete = function()
{
output.text = "Upload complete";
//here my code to add a row
}
The first time it works fine.
But if I upload another file, the onComplete function is run 2 times (I see that cause 2 rows are added to my grid). If I upload a third file, it is run 3 times, etc.
How weird is that :)
Have you ever seen that before?
You mean filtering the file types in a regular file upload?
Nathbot,
That is a known bug that we have in all the file upload examples. It happens because a new listener gets added every time the browse button is clicked. Nahuel told me that he was going to fix it, but he's been very busy... :)
There is no way to get anything back directly. You need to know the new name in advance or do something else such as store it in a db or whatever. I think I have an example of renaming the file in the downloadable zip in this post:
http://www.asfusion.com/blog/entry/showing-an-image-after-upload
Thanks for your reply.
Have just changed nameconflict to skip and added a directory check and overwrite prompt to the custom tag.
Any way around this?
Steve
Here is what I am trying to do.
May be someone can help me with it.
I want the same progress bar, but I am going to be uploading videos onto my website.
After the file gets uploaded I want to convert the video into flash. And so I would like to tell the user through the progress bar, how far it is not only form being uploaded but from being converted as well.
Let me add to this by saying if anyone know of a good way of converting AVI/MPEG/MOV into flash on the fly, right after a user uploads the video
I'd really appreciate it.
So far I am just calling cfexecute to call a cammand line version from geovid.
What would be greate if you could do this through action script.
When I try your code at my local develop machine, it works fine but, when I put code in product server, it through 'IO Error' on me. Any idea?
thanks,
this may seem like a dumb question but i want to double check as my attempts have failed. If i had an images table my database that related to the image files, wouldn't i place the insert/update code in the upload.cfm file? i've tried this using my DAO but i just get a http 500 error. The image still updates fine, and if i take the script that updates the database to another page it processes fine, so i must be missing something within the custom tag. Any suggestions would be greatly appreciated!
thanks again,
David
Whenever I try to upload a file that is over 100MB, I get an IOerror right after progress shows 8.5MB. I tried that with many file types and the error always happens there (between 8th and 9th MB).
I have no problems uploading 'smaller' files (largest size I was able to upload was 85MB) - it looks like the problem exists only with files which are over 100MB!
Is there a way around this sproblem. I spent a lot of time on this project and at this time the client refused to pay since his main requirement is not acomplished. Any help would be appreciated.
I've tried the tag on two seprate installations of MX 7 on Win2003(also from to different workstations using flash 8) and still no response from clicking the "Choose File" button.
Flash loads up nice and the "choose file" button highlights but no response after that.
Any Ideas?
The tag will not work because it uses Flash Forms, which were introduced in CF 7. If you want to use the Flash 8 uploading features, you will have to go to plain Flash. Check this post: http://blog.oinam.com/archives/2005/08/flash-8-file-upload-download/
After having it in production for couple of weeks I must pull it down. Upload works great when you upload small files, but whenever you try to upload large files (up to 100MB) there is no guarantee that upload completes. I get complaints from my customers every day! - 10 to 20% uploads throws an IOerror sometime during the upload - it's ridiculous!
When I test it, I can upload a 30MB file couple of times without a problem, but on the next try it errors out - there is no rule on when or how it happens. BTW, I tried to find any info on IOerror and how to recover from it...no luck!
I have a question. I have the example uploading... kinda.
When I choose a file I get "undefined" for the file name and in the details I get:
Name: undefined
Size: undefined bytes
Type: undefined
Creation Date: undefined
Modification Date: undefined
What am I doing wrong?
Thanks so much for the great code.
- Josh
If I want to run another routine after the file is uploaded like... resizing the image or something. Is there a call or something I can listen for that would let me know the upload is complete and then I could call a program like alagad image or something like that to do the image resize?
Thanks,
Josh
I would run that right below the file upload (after cffile). Otherwise, you can also do stuff by implementing the onComplete function (see post), but in order to communicate with the server there you either have to use remoting or submit the form.
Thanks.
Harold
Just have a quick question. How would you go about uploading a file out of flash using a cfc?
I've run into errors due to the remoting content-type being application/x-amf instead of the required octet-stream. I currently have a separate script file that does the upload. The issue is that the record is being inserted into the db within the cfc script while the file name is set to makeunique when uploaded. Of course, if the file is renamed, the cfc is not aware of this and the original file name is inserted into the record. Perhaps I should have the upload script query the same table using @@Identity and comparing the server file name with what is in the table.
The web site I listed along with the post is the app I'm working on. If you check it out go to 'candidate registry' and click 'register' on the next screen.
Thanks so much for any tips!
Sean
See my replies:
http://www.asfusion.com/blog/entry/file-upload-explained-and-expanded#comment-1378
http://www.asfusion.com/blog/entry/file-upload-explained-and-expanded#comment-1381
http://www.asfusion.com/blog/entry/file-upload-explained-and-expanded#comment-635
Sean,
The upload is done via a form POST (done by the Player), so it is not via Remoting (amf). When you do the upload (say it is upload.cfm), you can do other things there, such as calling a CFC that does some processing. We've done that in the Flex version of the real estate application. In that case, we resize the image, but you could insert things in the database or do whatever you want to do. Although it is not the best solution, it is the only way of doing with the current implementation of the upload in the Flash Player.
I using filereference with PHP and asp.net. With PHP, working very fine. In asp.net, locally working fine but on deplyoment server, itz behaviour becomes bull shit. The same file gives, 500 error or io error. post data size and upload size on server is enough but....BUT....dz anyone help?
There were issues with https (http://www.powersdk.com/ted/2005/11/using-flash-player-under-https-with.php), but it is not impossible. Have you tried adding the port to the file upload path (https://www.example.com:443/upload.cfm)?
uploadSwf.upload("https://jobs.lansg.com:443/HR/ResumeUploadAction.cfm?resume=" + myform.ContactID + myform.FileExtension);
I get no errors but I get no file either.
the link you supplied me was helpful but I don't know anything about implementing crossdomain.xml or the loadpolicyFile he talked about: I got a 404 error browsing to it. Can you give me pointers on how to use this info? (System.security.loadPolicyFile('https://flexdemos.cynergysystems.com/support/crossdomain.xml');)
What I would do first is to use Fiddler or similar to see where the upload is trying to get posted and see if I get any errors there. By the way, I think you have a semicolon that shouldn't be there before the + sign.
Regarding the crossdomain.xml file, see this technote: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=tn_14213
Nevermind about the semicolon, I think it got there because of the automatic linking.
I am trying to get the file upload in flash working.It works only for some types of file extensions like .txt,doc,.xml but when i select an image or a file with extesion .xls,the filesize is returned as zero and as a result the upload script never gets called.
Any help would be greatly appreciated
Thank u so much
Can't really help you with the info you give. Are you sure it doesn't upload "any" image? Maybe the directory is not accessible, I don't know. Also check what extensions you are allowing in the code.
<cfif attributes.progressInfo>uploadListener.onComplete = function()
{
output.text = "Upload complete";
"<CFLOCATION URL="anotherpage.cfm">";
<cfif len(onComplete)>#onComplete#();</cfif>
}
Any ideas?
i also tried this
<SCRIPT language="JavaScript"> top.location.replace("http://www.yahoo.com");</SCRIPT>
It's ColdFusion code (.cfm file extension), therefore, your server needs to have ColdFusion 7.01 or above to make it work.
Angel,
I think you are mixing up the code of the custom tag with this code. If you use the code in this post, create an onComplete function (you can't use CF or javascript inside ActionScript code):
uploadListener.onComplete = function(){_root.getURL('address where you want to go');
}
Similar to others, I have come across an "IO Error" issue when using the file upload from different work stations. The odd thing is, I'm using the same browser, files, and code...but run into the "IO Error" on some work stations and not others. The file sizes are all less than 2-3KB. Is there some file or files that are needed that may not be downloading properly to certain workstations? (I'm out of other ideas)
Thanks in advance,
Kevin
I have 2 pages (page1.cfm and page2.cfm). I put your fileupload component and a submit button in my first page. But I want the uploading take place only when it hits my second page (after I click the submit button). How to do about that? In your example, you call the uploading function when user click a button with onClick event in the first page.
Looking forward for your reply.
Thanks in advance
Keiko
I apologize for bringing problems and not solutions to this thread. I am working with a flash multiple-file uploader with a PHP server-side script. I can upload one large file (over 80 MB) or multiple small files ( less than 2.5 MB) with no problems. The problem comes when I upload two or more large files (over 8 MB). When I invoke the upload function, the computer freezes (actually freezes even the mouse) for about 10 min, then it would resume its operation and the upload process fails with this message “flash script running slow, computer might become unresponsive”. I have tried other flash uploaders found on the web, even the example in the Flash 8 help files, but I run into the same problem with multiple large files. Anybody ran into this problem before? Can anyone shed some light on this issue? Help is very much appreciated.
Z
I am having a problem using this with security on my site... It seems that if the upload.cfm page contains the below code the application makes it look like it is moving the file (the progress bar goes) but the file does not move... Any thoughts? THANKS! GREAT AP
<cfif NOT isdefined ("form.emp_usn") OR NOT isdefined ("form.emp_pwd") OR NOT structkeyexists(form,"Filedata")>
<cfif not IsDefined ("Session.authenticated")> <cfinclude template="/loginform.cfm">
<cfabort>
</cfif>
</cfif>
Having Trouble.
Someone mentioned they had an example of how to do it.
Unfortunately, in the upload action file, you only receive "Filedata" and no other field (see my comments on passing url variables as a workaround), so you cannot check for form.emp_usn for example. Neither you will achieve anything by cfincluding the login form since the upload happens "in the background". You will see the file uploading, but CF will not do anything with that data, since you have that <cfif>.
myname,
See my comment above: http://www.asfusion.com/blog/entry/file-upload-explained-and-expanded#comment-889
George,
If I understand your question correctly, you want to bind the grid data to the field? If so, the field that shows the file name is just an input field, you can use your regular binding. (Now that doesn't mean you will be able to upload anything that gets shown there, it's just a string in a text input at that point)
You are correct in what I am asking.
I did try and bind like:
<cf_flashUpload name=ImageBottle actionfile="Upload" fileTypes="*.jpg" bind="{ProdList.selectedItem.ImageBottle}">
Im thinking this should show the name of the image that is being used. Its perfect that it wouldnt upload that then. I just want the user to see what image is attached to the rest of the data. Then make the decision to select a new image or just edit some of the text and update that. leaving the old image or changed to a new one. But I cant get the bind to show the file name in the input of the upload. Is my statement wrong?
Thanks
Your the best! I have all working perfect.
20 form fields 8 browse fields (bound to my grid), Add, Edit, Delete. So Great!
It seems I experience a problem about uploads over SSL on Firefox. I've tried many combinations of the cross-domain file and still have I/O error. On IE everything is OK... Have you found something that could help me ?
Thanks for your answers
actionFile="yourUploadFile.cfm?urltoken=#SESSION.urltoken#"
In Firefox it creates a new session when it goes to yourUploadFile.cfm, but in IE it preserves your current session. Hope this helps.
I posted a similar solution at: http://www.asfusion.com/blog/entry/file-upload-with-coldfusion-flash-forms#comment-253
I would use the hidden field as described there, otherwise, your form will recompile for each session created, as in your version, it would create different ActionScript code whenever session.urltoken changes.
I can get a file upload to work using (this one works):
<cfif isdefined("form.upload_now")>
<cffile action="upload" filefield="ul_path" destination= "uploadspot" nameconflict="makeunique" variable="FileName">
<cfdump var="form">
</cfoutput>
</cfif>
<cfform method="post" name="upload_form" enctype="multipart/form-data" id="upload_form">
<br>
File Name: <cfinput type="text" name="FileName" id="FileName" size="150" width="100" required="yes">
<br>
<cfinput type="file" name="ul_path" id="ul_path">
<br>
<cfinput type="submit" name="upload_now" value="submit">
</cfform>
I am guessing this is a security issue but I am not sure where to look (IIS or Cold fusion)
Thanks in advance
I needed a form that captured user info along with photo.
In the upload script, check for the value of fileNameField, if it is empty, make a custom function call
var fileNameField = fileNameField;
if (fileNameField.text == '') {
_root.getURL("uploadNoPic.cfm?postData=" + myForm.postData,"_parent","POST" );
}
else {
var uploadSwf = textArea.label.upload;
uploadSwf.upload("upload.cfm?userid=" + myForm.userid);
uploadBtn.enabled = false;
browseBtn.enabled = false;
}
At the bottom of the uploadListner.onComplete function add another getURL call such as:
uploadListener.onComplete = function()
{
var userid = myForm.userid;
output.text = "Profile Saved.";
uploadBtn.enabled = false;
browseBtn.enabled = true;
_root.getURL("completeUpload.cfm?photo_name=" + myForm.fileNameField + "&userid=" + myForm.userid + "&postData=" + myForm.postData,"_parent","POST")
}
I did need to reference the file uploaded with the data posted later and that was done using a temp table in the db and a hidden field on the form.
The initial upload saves the picture and writes file name and user identifier that is stored in the session as a record in the temp table.
The getURL call in the complete function calls an action page that queries the temp table for the filename and user id match.
Then inserts into actual table the complete record with post data, photo name, and userid. It then deletes the temp record and cflocation redirects.
Pretty off the wall hack, but it works for the time being.
Bacardi
Has anyone figured out the rhyme or reason behing the IOError?
Sometimes I get them and sometimes I don't and I haven't been able to identify any one thing that I'm doing differently from one upload to the next.
TIA,
Bacardi
I have a fuse box application. Multiple tab navigation flash form. the code i am using is strait forward.
<cfformitem type="text" style="fontWeight:bold">upload</cfformitem>
<cf_flashUpload name="defaultFile" actionFile="user/upload.cfm" swf="user/fileUpload.swf">
<cf_flashUploadInput />
</cf_flashUpload>
The uploader brings up the dialog box and locates the file fine, but when submitted I get the 404 error. I have read every post on this issue and tried every option I can think of.
1. Placing the upload.cfm file in the root directory of the fuseapp next to the index file.
2. placing the upload file in the parsed directory (just thought i would try.
3. using /user/upload.cfm
4. using user/upload.cfm
5. upload.cfm
I even took the full example folder that i downloaded from you and tried it as it was (that worked fine) so i know it is not your issue, but i am not getting it to find the upload file.
Any help would be greatly appreciated!
I upload correctly a file but i want store also kb dimension in a database table.
How i can do it ?
thanks
TIA
Upload.cfm works fine with a ColdFusion/html form, but not this flash form. There is no login prompt.
What would cause it to go immediately to 100% progress bar and require login?
Thanks,
Don
I've an issue. I've a flash uploader to upload multiple files(pdf, doc) to a folder in the server.The upload is working fine. I want to download the files to my desktop using the core ftp. But, I see the permission of the folder as 600 and I cannot download them to my pc either. So what's wrong and how to fix it??
The app is a Fusebox application, but that really shouldn't matter. I have spent a lot of time on this and still nothing. Other events on the button work, such as GetURL(), etc.--just not the browseScript. Someone please help if you have an answer!
Thanks in advance.
i try to use your source, but my browser brings always the error "lc_id" is undefined on line 26 ???
any idea what this mean?
Thanks in advance.
See documentation on cffile action="upload". You will get the uploaded file name, size, etc, such as cffile.fileSize You'll get that information in the upload.cfm file right after using cffile for uploading.
Don,
Authentication does not work with flash upload. If you use browser prompting authentication, flash upload does not support it. I don't think you use some kind of redirection to a login form, but that doesn't work either, since flash calls this file in the background.
Lance,
Make sure the path to the upload swf file can be loaded. Use absolute paths when in doubt (ie: /myassets/fileUpload.swf)
Manuel,
See this:
http://www.asfusion.com/blog/entry/file-upload-with-coldfusion-flash-forms#comment-1795
If I know what it takes to make it work, then I can change my security setup accordingly. I'd appreciate any further assistance.
Don