Wednesday, September 19, 2007

SWFUpload Revision 7.0 Beta

I have almost completed work on Revision 7.0. I think the coding on the SWF and JS files is done. But I have not had time to convert the demos. I decided to post a "Beta" since I don't know when I'll have time to come back to the demos and documentation.

The R7 beta will be available at http://swfupload.praxion.co.za/

R7 Notes

The API has change significantly for R7 (that's why is R7 and not R65). You won't be able to drop this in over SWFUpload v1.0.2 or any of the other Revisions.

This version uses a different event model which introduced some issues with the Flash to JavaScript and JavaScript to Flash calls. I think I've resolved them but I'm sure someone will figure out a way to bring the bug up again. The long of the short of it is that when Flash calls to JavaScript if that JavaScript thread calls back in to Flash then Flash misbehaves. In order to work around this I use a setTimeout (the Timer class in ActionScript) to make calls from Flash to JavaScript. This effectively makes the call on a separate thread and works around the problem. The only place that this is not done is the call to the uploadStart event since uploadStart is required to return true or false. If you make any calls in to the Flash from uploadStart then you run the risk of triggering this issue.

Several pieces of functionality will appear to have been removed from this version. Almost everything that has been removed is still doable using the new events. There are comments in the code that explain some things and once the demos are complete hopefully you will be able to see how everything works.


Changes
  • Removed the settings: begin_upload_on_queue, validate_files, and use_server_data_event.
  • Changed the setting: upload_target_url to upload_url.
  • The events called are as follows and are listed in their approximate order:
    • fileDialogStart: Called from Flash immediately before the File Dialog is displayed.
    • fileQueued: Called once for each file that is added to the queue.
    • fileQueueError: Called once for each file that fails to be added to the queue.
    • fileDialogComplete: Called after all selected files have been processed.
    • uploadStart: Called for each file in the queue immediately before it is uploaded. Return true to continue the upload. Return false to skip the upload.
    • uploadProgress: Called periodically to provide upload status for the current file.
    • uploadError: Called when an error occurs on an upload or if an upload is cancelled.
    • uploadComplete: Called when an upload finishes successfully.
    • fileComplete: Called after an upload and SWFUpload is ready to allow another upload to begin. This is called even if an upload is cancelled or has an error.
  • Removed the queueComplete event and the cancelQueue command.
  • Enhanced the cancelUpload command so if it is not passed a File ID then the current upload or first file in the queue is cancelled.
  • File cancelling behavior has changed. If an in-progress upload is cancelled the uploadError event is fired and the fileComplete event is fired. If the file is not currently uploading then only the uploadError event is called.
  • Added a GetStats command. This returns an object that contains the number of successful uploads, the number of files remaining in the queue (excluding the current upload, if any), the number of queue errors and the number of upload errors.
  • Added a file_status property to the File Object.
  • Added a single file browser. This allows the user to only select a single file for upload.
Some of the Command names, Event names, and Error code constants have changed. See the source code for the updated names.

43 comments:

  1. excellent news. I'll try to use this today and let you know what it gives.
    I came back because I had a issue with the previous releases. Did you have similar problems? the problem I have is that when you upload something your user is authenticated only when you use internet explorer. even when you are logged in the user is anonylous in the upload.aspx when you use opera and firefox... have you had a similar issue?

    ReplyDelete
  2. There is a bug in the NSAPI Flash Player plug-in (the plug-in used by all browsers except IE which uses ActiveX).

    The cookies from the browser are not sent with the upload. The breaks both Forms Authentication and Cookie-based Sessions in ASP.Net applications.

    I have been able to work around the Forms Authentication piece by sending the cookie value in the Post and manually restoring the authentication server-side. I have not found a way to manually restore the session.

    There is a separate issue with HTTP-based authentication. For me, HTTP-based authentication seems to work, sometimes, in IE but not in other browsers.

    ReplyDelete
  3. Hi,

    Did you know swfupload returns a -10 error if the server returns with http status 201 (created).

    You should think of fixing this, because 201 is definitely not an error.

    P.S. keep up the good work, this is the best http upload tool out there.

    ReplyDelete
  4. @jake

    To get around the cookie (it's name and value) issue, just get the cookie via it's name which you should know and then put it in the request's post body.

    JS class for cookies:

    var Cookie = {
    set: function(name, value, daysToExpire) {
    var expire = '';
    if (daysToExpire != undefined) {
    var d = new Date();
    d.setTime(d.getTime() + (86400000 * parseFloat(daysToExpire)));
    expire = '; expires=' + d.toGMTString();
    }
    return (document.cookie = escape(name) + '=' + escape(value || '') + expire);
    },
    get: function(name) {
    var cookie = document.cookie.match(new RegExp('(^|;)\\s*' + escape(name) + '=([^;\\s]*)'));
    return (cookie ? unescape(cookie[2]) : null);
    },
    erase: function(name) {
    var cookie = Cookie.get(name) || true;
    Cookie.set(name, '', -1);
    return cookie;
    },
    accept: function() {
    if (typeof navigator.cookieEnabled == 'boolean') {
    return navigator.cookieEnabled;
    }
    Cookie.set('_test', '1');
    return (Cookie.erase('_test') === '1');
    }
    };

    ReplyDelete
  5. RE: HTTP 201 Issue:

    This is an issue with Flash. Unless the server returns a 200 status the FileReference fires an HTTPError event. I decided to reflect the Flash behavior and so the uploadError event is called. The HTTP status code is passed in the message parameter for this event so you can check the status code and handle things properly in the UI. The GetStats function will still how an upload_error instead of a successful upload of course, but otherwise it should work fine.


    RE: Cookies

    Thanks for the cookie code. In a previous Revision I had cookie pulling code built in but then decided to take it out.

    The issue here isn't getting the cookies. The issue is that in ASP.Net you cannot manually override the session like you can in with a simple session_start($session_id) in PHP.

    I suspect that you might be able to work around this with an HTTPModule or HTTPHandler. If someone want to write one that'd be cool.

    ReplyDelete
  6. Good news, can't wait to see the application demo and why not a bit of doc.

    As I would like to use your swfupload release with Rails, I'll be pleased to submit a rails version of the application demo and why not a rails plugin to make the usage even easier.

    Keep on great work, thanks a lot for it.

    ReplyDelete
  7. Anonymous1:28 AM

    Hi, Jake, with flash 9.0r16, I'm getting "Error #2007" when running the upload tool. Do you know why? Later versions of flash seem to be fine.

    ReplyDelete
  8. also wondering how i should compile the as code once i modified it. i'm always getting "classes/SWFUpload.as:1: characters 0-7 : parse error Unexpected package"

    ReplyDelete
  9. When exactly are you getting the #2007 error? If you get some output in the debug console can you include enough of the output to see where/when the error occurs?

    As for compiling. I'm using FlashDevelop 3.0.0.beta3 to compile R7. I'm just winging it here on Flash and ActionScript 3 but I had to move the .as files out of the "classes" folder into the main project folder in order to get them to compile. Flash does the same annoying File Name/Path must match the Class/Package in order to compile as Java.

    ReplyDelete
  10. Anonymous9:07 AM

    Hi, Jake. Can you please tell if it's possible to return any error message from the server back to flash? Excellent work btw, great tool :)

    ReplyDelete
  11. as I tried to understand and reuse the demos for this revision, I saw that in swfupload.js in the SWFUpload.prototype.uploadError, there is a test for a ERROR_CODE_MISSING_UPLOAD_TARGET, shouldn't it be ERROR_CODE_MISSING_UPLOAD_URL ?

    ReplyDelete
  12. If the server returns any HTTP status code other than 200 then the uploadError event is called no other information from the server is sent.

    If the server returns a 200 status then uploadComplete is called. The second parameter is the server data which includes all the text returned by the server (excluding headers).

    This works well for PHP since any errors are usually just outputted in text without affecting the HTTP status code. It's best to catch all your errors and return something that your client side JavaScript can understand and act on.

    In ASP.Net any exceptions cause a 500 status code (unless you catch them first) so sending error related data back to the client can sometimes be a little more round about.

    Sample:
    var swfu = new SWFUpload(
      {
        lots of settings,
        upload_complete_handler: myUploadComplete,
        lots more settings
      }
    );

    function myUploadComplete(fileObj, server_data) {
        alert(server_data); // this pops up an alert with the text returned from the server
    }

    ReplyDelete
  13. @shadow walker:
    You are correct. That's what happens with manual refactoring ;)

    I've corrected in my source. Thanks for the bug report.

    ReplyDelete
  14. Hi,
    I gave 7.0 Beta a try today, and it works like a charm. Without documentation I got it working very quickly, the source is easy to read. Thanks for the great job.

    Question: when using a multi-file browser, how do I tell SWFUpload to limit the total size to a given value? That is, how do I tell what the "disk quota" is? If that's not possible, what would be the best way to emulate that?

    Cheers!

    ReplyDelete
  15. Very well documented in the code itself! Thank you this is working terrifically. Using Django.

    ReplyDelete
  16. As I am digging to make get a working upload with this version, I found some bug that may come directly from the flash plugin distributed for linux (9.0 r48).

    When I try to change the file_post_name, I only got the default name: 'Filedata'. I put some debug in the flsh and figured out that whatever I put s second argument of the file_reference.upload method, with the flash plugin for linux, the upload data is always sent named 'Filedata'. perhaps until this is fixed in a next flash release, you can put a warning in the docs.

    With the previous version, I was able to send data to server if I set the variable use_server_data_event to false. I'm not sure it was linked to this setting, but whatever the server would send as response (200, 500... with or without strings...) the file was uploaded and the flash detected it as completed and uploaded the text file in queue.
    But now, since this setting is not available, the flash detect the progress until 100% but not the completed file event and so never process the nest file in queue. maybe this option could return?

    ReplyDelete
  17. I'm glad R7 is working well for ya'll.

    @shadow walker:
    RE: Filedata.
    I'll look in to this and at least make a note. I only added this feature because I could and because someone once requested. Being able to change the "Filedata" name doesn't really do anything of value. It's just kinda nice to be able to do.

    Re: use_server_data & incomplete uploads.
    There is a known issue with Flash player. In the Flash Player when using the "Server Data" event instead of the "Upload Complete" event (and you can't use both) you _have_ to return data from the server. If you don't return data then "Server Data" never fires off. "Upload Complete" will fire but if you use "Upload Complete" then you cannot use "Server Data". In R62 this was the purpose of the "use_server_data" setting. When true it indicated to Flash to use the "Server Data" event and when false Flash used the "Upload Complete" event.

    In R7 I decide to remove all that and to always use the "Server Data" event. However, this means that your upload script *always* has to return some data or "Server Data" will never fire and your upload will never complete.

    In my upload script I make sure I always return something. E.g. echo " ";

    Try that and let me know.

    ReplyDelete
  18. I tried with the upload.php script and even add an "echo 'nothingbuttext';" at the very begining.
    From a windows/firefox client, the end of upload is well detected. From the linux/firefox the end of upload is never detected

    ReplyDelete
  19. Anonymous1:22 PM

    This is so great. Sadly, it doesn't seem to work with the beta flash player (Shockwave Flash 9.0 r60)

    ReplyDelete
  20. I tried to use R7 files along with the demo app from revision 6.2. I've managed to get it work except that the "server_data" variable (which is passed to the "fileComplete(fileObj, server_data)" function) is always undefined.

    Can anyone help?

    ReplyDelete
  21. As I was trying to find a bug report form at adobe site, I saw that a new version was pre-released today from http://labs.adobe.com/downloads/flashplayer9.html and after test, that this version fixed the Filedata bug and the dataserver response detection :-)

    ReplyDelete
  22. I have come across a problem. My script is reporting a "broken pipe" which normally occurs when the client closes before the server can send a response. I suspect this may very well be a problem with my server-side script. On the other hand it smells a bit like the Flash beta player isn't keeping its doors open for long enough to got a response. The debugger is reporting a 500 error from the server. Anyone else experience anything similar?

    ReplyDelete
  23. Finally resolved my problem - it was in the server-side script. Sorry about that.

    ReplyDelete
  24. could anybody provide a simple working R7 example somewhere? I have trouble getting it to work correctly.

    ReplyDelete
  25. I've added a working R7 demo to the site.

    I recommend using FireFox with FireBug to examine the source.

    I've been meaning to get the package together for a non-beta release but we've had plumbing problems at the ol' homestead and hot water comes first.

    ReplyDelete
  26. thanks for the quick reply :).

    however the demo on the site doesn't seem to work on firefox/linux (using nspluginwrapper to run a 32bit flash plugin on a 64bit ubuntu)

    SWF DEBUG: startFile(): File Reference found. Starting upload to ../multiuploaddemo/upload.php. File ID: SWFUpload_0_0
    SWF DEBUG: Event: uploadStart : File ID: SWFUpload_0_0
    SWF DEBUG: Event: uploadProgress: File ID: SWFUpload_0_0. Bytes: 33041. Total: 1016898
    ...
    SWF DEBUG: Event: uploadProgress: File ID: SWFUpload_0_0. Bytes: 1016898. Total: 1016898

    ... and it just sticks here. it, however works fine in windows.


    when running the code in my own app, it doesn't get further than:

    SWF DEBUG: startFile(): File Reference found. Starting upload to http://localhost/tl/endurance/admin.php?part=gallery&action=look&id=39&addthem=yes&fromajax=yes. File ID: SWFUpload_0_0
    SWF DEBUG: Event: uploadStart : File ID: SWFUpload_0_0

    in my ubuntu. however everything works fine in windows...

    do you have any idea what might be to blame here?

    ReplyDelete
  27. Some of Shadow Walker's later comments talk about Linux. You might first try the latest beta Adobe Labs Flash Player. But this doesn't really solve the problem since we want to be as compatible as possible. So here are some questions for you:

    Did R62 work for? R7 uses a very different call back method that could be causing issues in the Flash Player/Browser relationship.

    What is your test file size?
    Does the file upload complete? I realize that the uploadComplete/fileComplete events aren't firing but is the server-side receiving the entire file?

    ReplyDelete
  28. I upgraded flash to the lastest version from Adobe Labs and everything is working properly now.

    About versions and linux:

    I got 1.0.2 working almost properly, however it sometimes didn't upload the first file and went straight to the second one...

    The R62 demo was working without problems, however I had some trouble integrating it into my own code. I messed around with it for a while, but it wouldn't let me even select the files, it just did nothing.

    I tried getting R7 working by modifying the R62 demo and got it working more than with R62. However it wouldn't start uploading. I guess I had some callback functions set wrong.

    Using your R7 demo I saw what I had done wrong before and could get it almost working, however the upload button didn't do anything except changing the status of the first file to "uploading", then it got stuck. The official R7 demo however managed to send the first file to the server. I'm not sure if the server got the file or not (I guess not and then froze before getting any response.

    Upgrading the flash plugin made the code work in both the demo and my program.

    I will try to see if the file gets completely uploaded with R7 and the older flash player and report back.

    ReplyDelete
  29. Anonymous9:00 AM

    First off I have to say that this upload tool is great. It is too bad that you can't collaberate with the developers of the original SWFUpload. I find your version to far better than theirs.

    Now for my question: I am trying to understand the difference between the fileUploadLimit and fileQueueLimit. I understand the purpose of fileUploadLimit, so the fileQueueLimit seems redundant. Cay you please explain the difference between them?

    ReplyDelete
  30. I found a bug!

    When trying to return the double quotes character ( " ) back from php (in server_data), I get an error which I'm not able to resolve (seems to be in actionscript since my js functions don't get called at all).

    ReplyDelete
  31. Anonymous9:04 PM

    What happened to the upload_stop_handler?

    ReplyDelete
  32. @Chris: I have worked with the SWFUpload developers in the past and v1.0.2 is based on a design I submitted (which may be why it has so many proglems).

    I hang out at the SWFUpload forums providing support for v1.0.2 and my Revisions.

    But, I haven't heard from them for awhile. I don't think they intended to continue support or development. They were just very nice and shared a tool that they had developed as a part of their other work.

    RE: R7
    The Revision 7.0 design has brought to light some major problems in the Flash Player. I tried some work-arounds but they don't seem compatible with Linux Flash Players. I haven't decided what to do yet. I like the Event design in R7 but if I can't make it work within the limitations of the Player I'll have scrap it and do something different.

    ReplyDelete
  33. I figured that since you have to call Stop to stop the upload that you already know what is going on so you don't really need a "stopped" event to tell you what you just did.

    ReplyDelete
  34. How do I set an Accept header for the flash movie to send to the server?

    ReplyDelete
  35. Anonymous3:06 PM

    @jake re: stop event

    The stop event used to return the file object of the file that was beign uploaded at the time stop was triggered. It would be nice to give some response to the user that the file was stopped and will be uploaded again on restart.

    ReplyDelete
  36. Anonymous3:53 PM

    I don't get it, I wonder what is going wrong. Everything - nearly everything - is working fine, when I upload small files. If the files are over 1mb there is no progress anymore. Under 1mb files are uploaded. If click any button the browser completely crashes (FF 2.0.0.6 / IE 6 on win2000 testing on xampp).

    php.ini-settings are all correct. First thought the cms I am using is to blame, but even your demos 6.2/5.2 are not working for me.

    Any clue? I would be very sad I could not use you excellent script. ;-)

    P.S.: the demos on your server are working fine for me

    ReplyDelete
  37. Suggestions:
    1) In PHP.INI both post_max_size and upload_max_filesize must be large enough to accept your upload.
    2) Both values must not be larger than 2047M

    I always test in FireFox with Firebug and the "debug" setting set to "true". FireBug is indispensable for JavaScript development.

    Also, I'm working on a bug right now that could be related. If you are using the Server_Data option (always enabled in R7) I get serious problems (in IE) if any special escape sequences are in the data the server returns. For example, my upload.php had an error and so emitted (in part):

    c:\inetpub\wwwroot\swfupload\upload.php

    Well, the Flash to JavaScript interface cannot handle the \u which translates to mean "the following is a unicode character code". I have also had problems with \f and quotations marks.

    So make sure your upload.php always returns what you expect and don't return any escaped characters (Flash even misunderstands regular back slashes).

    If you want to discuss things in more detail use the official SWFUpload forum (which I frequent).

    ReplyDelete
  38. Anonymous6:21 PM

    Last time I post here, promised! :-D

    Finally solved my problem (with Fiddler) and you would not believe it. The problem was that IE was expecting the upload.php at another place than any other browser. So I put all the files in one directory and now it works.

    As I read in the previous comments there must me Server Data returned (empty echo), but this gives me other "problems" with headers already sent.

    Thx for your support.

    ReplyDelete
  39. I don't mind posts here but if you've got sample code and such it's much easier to go over things in the Forums.

    Also there are a lot of good tips in the forums that apply to R62/R7 specifically and SWFUpload in general.

    ReplyDelete
  40. I'm prepping an R7 beta 2 release. It should be posted tonight or tomorrow.

    I've made some changes with hopes of resolving some of the Event handler issues. Tip: Avoid making calls to SWFUpload methods while in an event handler. It should work now, but Flash Player has bugs and it's flakey.

    I've also fixed a Flash Player bug where strings were not escaped properly before being sent to JavaScript. This manifested itself by preventing the uploadComplete event while still getting uploadProgress events and the fileComplete event). An unfortunately placed backslash or quotation in the Server Data will no longer foul things up.

    ReplyDelete
  41. Excellent tool, thanks so much for developing and sharing it.

    One question - with a completely fresh install (no changes), when the flash app loads, it prompts me with a dialog "Where is the debugger or host application running?". The dialog title is Adobe Flash Player 9.

    The swfupload config setting is debug: false. Are there any other debug settings?

    ReplyDelete
  42. This is a message from your Flash Player. It sounds like you have a debug version of the Flash Player. I've never been able to get these to work but I understand they come with Flex, Flash Studio, or you can download it and install it from a stand-alone download.

    Of course there may be some build option that I have set that is triggering the debug message in your Player but I'm not sure what it is (I don't use a debug player).

    This is not related to a setting in SWFUpload but to how the swf file was built.

    I'll look in to it.
    I'll look in to it.

    ReplyDelete
  43. Anonymous3:47 PM

    I had the same message as Patrick, but was only occurring on one machine, and it came down to having a Flash Player with Debug Player.

    ReplyDelete