views:

501

answers:

3

We have a form with five <input type="file"/> elements that is in production and working great. We get request timeouts and MaxRequestLength exceeded errors on occasion. To prevent these errors, I planned to write some Javascript to upload the files one-at-a-time instead of all at once. Here is how I planned on doing this...

  1. On document.ready, inject a hidden iframe into page
  2. Change the <form> to target the iframe
  3. Disable all elements on the form (which prevents them from being POSTed)
  4. Enable one file-upload at a time and submit the form
  5. Wait for the response from the server
  6. When server response is printed into iframe, start the next upload
  7. When all uploads are done, refresh the page, which will invoke some server-side logic that populates a grid.

My problem is with number 5. Normally I think I could figure this out no problem, but I am just having one of those days where my brain is on strike. Here is my code thus far...

$(function() {
  $("<iframe/>").attr("src", "test.htm").attr("name", "postMe").hide().appendTo("body");
  $("form").attr("target", "postMe").submit(function(e) {
    e.preventDefault();
    $("#btnSubmit").attr("disabled", "disabled").val("Please Wait, Files are Uploading");

    for(var i = 1; i < 6; i++) {
      $("input[type=file]").attr("disabled", "disabled");
      $("#FileUpload" + i).removeAttr("disabled");
      $("form")[0].submit();
      // HELP!!!
      // How do I wait for server before next iteration?
    }

    location.reload(true);
  });
});

What kind of construct do I need here in order to "wait" for the server response before kicking off the next upload?

+1  A: 

I think you should listen for iframe's load event and perform input's switching in the handler. I completed with my own uploader today and this solution worked for me.

Alex Ustinov
Interesting approach!! Thank you very much, I am going to try this.
Josh Stodola
+1 I don't think that you're going to find a way to actually block and wait until the iframe loads; you'll want to make your code asynchronous, and get a callback when the iframe is ready for the next iteration.
Sixten Otto
Any chance you could show me some code Alex? I am struggling.
Josh Stodola
In short, my onload event handler on the frame is not getting fired. I assign the handler right after the form is submitted. Should I be doing this elsewhere?
Josh Stodola
You could find a working sample here: http://liveui.net/demo-bugtracker/Tasks/13?grid=demo-bugtracker%2fTasks%3fsortdir%3dAscending%26start%3d0The script currently working is a bit outdated (it is already two weeks old :) ) but you can find newest version that is much better in our download archive. Pay attention to 'jquery.uploadfield.js' file. You must pay attention to "this.iframe.bind('load', this.iframe, ..." line.
Alex Ustinov
I'm not sure about exact causes of your callback is silent but I had similar troubles specifying iframe.name and form.target attributes dynamically. So finally I decided to combine valid html with these attributes inlined and create html elements then.
Alex Ustinov
Yes, I had that issue too and got it resolved doing what you just said. However, my onload event still does not fire. The form is posting correctly, I just cant trap the event. And the page you link to gives me a Javascript error (Object Expected) on page load.
Josh Stodola
Found the JS file, but can't get it because of server-side error : http://liveui.net/XtensiveModules.axd/webforms/Resources/Scripts/jQuery.uploadField.js
Josh Stodola
Very! strange. The site perfectly works for me. So could you be so kind to tell me what browser do you use. Seems we've missed something. Btw I've only idea why load event may not be fired. Probably your response for POST request is empty while we have sending back some JSON with status information. Except this we do nothing special.
Alex Ustinov
PS: I would send you the uploader script by e-mail if I knew one.
Alex Ustinov
I got it to work! I had to assign the handler inline in the markup (yuck) in order for it to fire consistently: ` onload="iframeLoad();"` Of course, I had to have something in the function to not trigger it on the very first load. Oh well, at least it is working. And I wrap it all in a try/catch, in the catch I just submit the form naturally so there are no down-falls with this solution. Thanks!!
Josh Stodola
A: 

Just FYI: jquery.forms plugin is all about making ajax form submitions. I use this plugin to submit a form (such as a file upload) in a separate iframe which the plugin takes care of automatically, and gives you a nice callback when completing.

This way most work for you is done.

http://jquery.malsup.com/form/

Dmitriy Likhten
Nice! I like the callback, I am going to dig into this code and see how it works, but I probably will not be using the plugin.
Josh Stodola
There's nothing there that will do the uploads one at a time, which is ultimately what I am after.
Josh Stodola
Step 1: Create a file upload mechanism using the plugin.Step 2: Use the success handler to trigger step 1 again.And so on.Remember it has all the jquery ajax events callbacks.
Dmitriy Likhten
+3  A: 

I've had a lot of success lately using Uploadify--it's very configurable, free, and allows for multiple-uploads. It also provides the option for callback functions allowing you to really configure it any way you want.

http://www.uploadify.com/

jnunn
Are you serious? It requires Flash. No way in hell would I ever use that.
Josh Stodola
What's wrong with Flash?
Kevin Tighe
Why not? SWFUpload and consorts work great, and they open a lot of possibilities for file uploads that vanilla HTML/JS don't have.
Pekka
I don't care what you are saying about Flash. I'm never goin to use it. Read the first comment I left on the question.
Josh Stodola