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...
- On document.ready, inject a hidden iframe into page
- Change the
<form>
to target the iframe - Disable all elements on the form (which prevents them from being POSTed)
- Enable one file-upload at a time and submit the form
- Wait for the response from the server
- When server response is printed into iframe, start the next upload
- 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?
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...
- On document.ready, inject a hidden iframe into page
- Change the
<form>
to target the iframe - Disable all elements on the form (which prevents them from being POSTed)
- Enable one file-upload at a time and submit the form
- Wait for the response from the server
- When server response is printed into iframe, start the next upload
- 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?
Share Improve this question edited Dec 23, 2009 at 15:28 Josh Stodola asked Dec 2, 2009 at 15:02 Josh StodolaJosh Stodola 82.6k48 gold badges186 silver badges229 bronze badges 6- I should note that I want to write this code myself, not use some fancy plugin with a bunch of dependencies. – Josh Stodola Commented Dec 2, 2009 at 15:09
- If this bee too much of a pain, I might just try to use use five iframes! That's the last thing I want to do, but it might be what I have to do. – Josh Stodola Commented Dec 2, 2009 at 15:19
- 1 @Stodola Nobody wants anything to do with flash' is really subjective. What is your problem with Flash? I was trying to give you more information regarding Uploadify. ' I dont understand why you want to reinvent something that already works perfectly if you just look around for other solutions that exist. – Josh Mein Commented Dec 23, 2009 at 15:25
- @jmein Flash is third-party. It does not work on 64-bits. It has a dependency. It's annoying. It's inaccessible. It has security problems. Call it subjective all you want; nobody I know would ever use it in a production scenario. It's a toy for children. – Josh Stodola Commented Dec 23, 2009 at 15:30
- @JoshStdolla Then why does Hulu work on my 64 bit machine? Hulu uses flash. – Bryan Denny Commented Dec 23, 2009 at 15:36
5 Answers
Reset to default 2I'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./
I think you should listen for iframe's load event and perform input's switching in the handler. I pleted with my own uploader today and this solution worked for me.
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 pleting.
This way most work for you is done.
http://jquery.malsup./form/
It can be done with the help of jQuery's queue method and load event.
<!DOCTYPE HTML>
<html>
<head>
<script src="http://ajax.googleapis./ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script>
//here's an upload script
(function($){
//make 'em accessible within the scope
var $iframe, $form;
$(document).ready(function(){
//create 'em only once, but use 'em many times
$iframe = $('<iframe name="iframe" id="iframe" style="display:none"></iframe>').appendTo('body');
$form = $('<form method="post" enctype="multipart/form-data" target="iframe" style="display:none"></form>').appendTo('body');
});
var iframeUpload = $({});
$.iframeUpload = function(s){
iframeUpload.queue(function(next){
//as we only wanna this new event
$iframe.load(function(){
//we must unbind the old one
$iframe.unbind('load');
//success or error, the question is up to you
s.success();
//but remember to remove or replace the old stuff
$form.find('input').remove();
next();
});
$form.attr('action', s.url).append(s.file).submit();
});
};
})(jQuery);
//and this is how to use the script
(function($){$(document).ready(function(){
$('input[type="submit"]').click(function(){
$('input[type="file"]').each(function(){
$.iframeUpload({
url: 'http://example./upload.php',
file: this,
success: function(){
console.log('uploaded');
}
});
});
});
})})(jQuery);
</script>
</head>
<body>
<!-- here are multiple files -->
<input type="file" name="file" />
<input type="file" name="file" />
<input type="file" name="file" />
<!-- to upload -->
<input type="submit" />
</body>
</html>
I was able to do this, by starting with the code at A Strategy for Handling Multiple File Uploads Using Javascript. That code uses an XMLHttpRequest for each file, but actually doesn't check the result from the server. I modified it to wait for the result from the server, sequentially, as follows:
var fileNumber = 0
var fileList = [] // see the code linked above for how to handle the fileList
var resultPane = document.getElementById('resultpane') // a textarea box
sendNext = function() {
if (fileNumber >= fileList.length) {
resultPane.value += 'Done uploading '+fileNumber+' files\n'
return 0
}
var formData = new FormData()
var request = new XMLHttpRequest()
request.onreadystatechange = function() {
if (request.readystate == XMLHttpRequest.DONE) {
resultPane.value += request.responseText // show whatever the server said about each file
sendNext() // and send the next file
}
}
formData.set('file', fileList[fileNumber])
request.open('POST', 'https://example./upload-receiver')
request.send(formData)
resultPane.value += 'Sending file number '+fileNumber+'\n'
fileNumber++
}