Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
406 views
in Technique[技术] by (71.8m points)

jquery - HTML5 multiple file upload: upload one by one through AJAX

I have a multiple files upload form:

<input type="file" name="files" multiple />

I am posting these files with ajax. I would like to upload the selected files one by one (to create individual progress bars, and out of curiousity).

I can get the list of files or individual files by

FL = form.find('[type="file"]')[0].files
F  = form.find('[type="file"]')[0].files[0]

yieling

FileList { 0=File, 1=File, length=2 }
File { size=177676, type="image/jpeg", name="img.jpg", more...}

But FileList is immutable and I can't figure out how to submit the single file.

I think this is possible as I saw http://blueimp.github.com/jQuery-File-Upload/. I don't want to use this plugin however as it's as much about learning as the result (and it would need too much custimizing anyway). I also don't want to use Flash.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

For this to be a synchronous operation, you need to start the new transfer when the last one is done. Gmail, for example, send everything at once, concurrently. The event for the progress on AJAX file upload is progress or onprogress on the raw XmlHttpRequest instance.

So, after each $.ajax(), on the server side (which I don't know what you'll be using), send a JSON response to execute the AJAX on the next input. One option would to bind the AJAX element to each element, to make things easier, so you could just do, in the success the $(this).sibling('input').execute_ajax().

Something like this:

$('input[type="file"]').on('ajax', function(){
  var $this = $(this);
  $.ajax({
    'type':'POST',
    'data': (new FormData()).append('file', this.files[0]),
    'contentType': false,
    'processData': false,
    'xhr': function() {  
       var xhr = $.ajaxSettings.xhr();
       if(xhr.upload){ 
         xhr.upload.addEventListener('progress', progressbar, false);
       }
       return xhr;
     },
    'success': function(){
       $this.siblings('input[type="file"]:eq(0)').trigger('ajax');
       $this.remove(); // remove the field so the next call won't resend the same field
    }
  });
}).trigger('ajax');  // Execute only the first input[multiple] AJAX, we aren't using $.each

The above code would be for multiple <input type="file"> but not for <input type="file" multiple>, in that case, it should be:

var count = 0;

$('input[type="file"]').on('ajax', function(){
  var $this = $(this);
  if (typeof this.files[count] === 'undefined') { return false; }

  $.ajax({
    'type':'POST',
    'data': (new FormData()).append('file', this.files[count]),
    'contentType': false,
    'processData': false,
    'xhr': function() {  
       var xhr = $.ajaxSettings.xhr();
       if(xhr.upload){ 
         xhr.upload.addEventListener('progress', progressbar, false);
       }
       return xhr;
     },
    'success': function(){
       count++;
       $this.trigger('ajax');
    }
  });
}).trigger('ajax'); // Execute only the first input[multiple] AJAX, we aren't using $.each 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...