jQuery HTML5多文件上传:通过AJAX一一上传

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13656066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 12:51:06  来源:igfitidea点击:

HTML5 multiple file upload: upload one by one through AJAX

jqueryhtmlajaxfile-uploadasyncfileupload

提问by Mark

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).

我正在用 ajax 发布这些文件。我想一一上传选定的文件(为了创建单独的进度条,出于好奇)。

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.

但是 FileList 是不可变的,我不知道如何提交单个文件。

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.

我认为这是可能的,因为我看到了http://blueimp.github.com/jQuery-File-Upload/。然而,我不想使用这个插件,因为它与学习和结果一样多(无论如何它都需要太多的自定义)。我也不想使用 Flash。

回答by pocesar

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 progressor onprogresson the raw XmlHttpRequestinstance.

为了使这成为一个同步操作,您需要在最后一个传输完成后开始新的传输。例如,Gmail 会同时发送所有内容。AJAX 文件上传进度的事件是progressonprogress在原始XmlHttpRequest实例上。

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 successthe $(this).sibling('input').execute_ajax().

因此,在每个 之后$.ajax(),在服务器端(我不知道您将使用什么),发送一个 JSON 响应以在下一个输入上执行 AJAX。一种选择是将 AJAX 元素绑定到每个元素,以简化操作,因此您可以success$(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:

上面的代码将用于 multiple<input type="file">而不是 for <input type="file" multiple>,在这种情况下,它应该是:

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 

回答by Nathan Kot

This looks like a very good tutorial, just what you're looking for.

这看起来是一个非常好的教程,正是您正在寻找的

That noted, uploading via vanilla ajax isn't supported in all browsers, and I would still recommend using an iframe. (I.E dynamically create an iframe and POST it using javascript)

需要注意的是,并非所有浏览器都支持通过 vanilla ajax 上传,我仍然建议使用iframe. (IE 动态创建一个 iframe 并使用 javascript 发布它)

I have always been using this scriptand I find it very concise. If you want to learn how to upload via creating an iframe, you should dig through it's source.

我一直在使用这个脚本,我觉得它非常简洁。如果你想学习如何通过创建 iframe 上传,你应该挖掘它的源代码。

Hope it helps :)

希望能帮助到你 :)

Extra edit

额外编辑

To create progress bars with the iframe method, you will need to do some work server-side. If you're using php, you can use:

要使用 iframe 方法创建进度条,您需要在服务器端做一些工作。如果您使用的是 php,则可以使用:

If use nginx you can also choose to compile with their Upload progress module

如果使用 nginx 你也可以选择使用他们的上传进度模块进行编译

All of these work the same way - every upload has a UID, you will request for the 'progress' associated with that ID at consistent intervals via ajax. This will return the upload progress as determined by the server.

所有这些都以相同的方式工作 - 每个上传都有一个 UID,您将通过 ajax 以一致的时间间隔请求与该 ID 关联的“进度”。这将返回由服务器确定的上传进度。

回答by hluchjak

I was facing same problem and came with this solution. I simply retrieve form with multipart, and in recursive call ( file after file ) start ajax request, which only calls next when is done.

我遇到了同样的问题,并提供了这个解决方案。我只是用 multipart 检索表单,并在递归调用(文件后文件)中启动 ajax 请求,它只在完成时调用 next 。

var form = document.getElementById( "uploadForm" );
var fileSelect = document.getElementById( "photos" );
var uploadDiv = document.getElementById( "uploads" );

form.onsubmit = function( event ) {
    event.preventDefault(  );

    var files = fileSelect.files;
    handleFile( files, 0 );
};

function handleFile( files, index ) {
    if( files.length > index ) {
        var formData = new FormData(  );
        var request = new XMLHttpRequest(  );

        formData.append( 'photo', files[ index ] );
        formData.append( 'serial', index );
        formData.append( 'upload_submit', true );

        request.open( 'POST', 'scripts/upload_script.php', true );
        request.onload = function(  ) {
            if ( request.status === 200 ) {
                console.log( "Uploaded" );
                uploadDiv.innerHTML += files[ index ].name + "<br>";
                handleFile( files, ++index );
            } else {
                console.log( "Error" );
            }
        };
        request.send( formData );
    }
}

回答by Milan Krushna

Using this source code you can upload multiple file like google one by one through ajax. Also you can see the uploading progress

使用此源代码,您可以通过ajax 一一上传多个文件,例如google。也可以看到上传进度

HTML

HTML

 <input type="file" id="multiupload" name="uploadFiledd[]" multiple >
 <button type="button" id="upcvr" class="btn btn-primary">Start Upload</button>
 <div id="uploadsts"></div>

Javascript

Javascript

<script>

function uploadajax(ttl,cl){

var fileList = $('#multiupload').prop("files");
$('#prog'+cl).removeClass('loading-prep').addClass('upload-image');

var form_data =  "";

form_data = new FormData();
form_data.append("upload_image", fileList[cl]);


var request = $.ajax({
          url: "upload.php",
          cache: false,
          contentType: false,
          processData: false,
          async: true,
          data: form_data,
          type: 'POST', 
          xhr: function() {  
      var xhr = $.ajaxSettings.xhr();
      if(xhr.upload){ 
        xhr.upload.addEventListener('progress', function(event){
                        var percent = 0;
                        if (event.lengthComputable) {
                            percent = Math.ceil(event.loaded / event.total * 100);
                        }
                        $('#prog'+cl).text(percent+'%')

                    }, false);
       }
      return xhr;
     }    
      })
      .success(function(res,status) {

        if(status == 'success'){

            percent = 0;
            $('#prog'+cl).text('');            

                $('#prog'+cl).text('--Success: ');

            if(cl < ttl){
                uploadajax(ttl,cl+1);
            }else{
               alert('Done ');

            }     

            }

      })
      .fail(function(res) {
      alert('Failed');
      });

}



$('#upcvr').click(function(){

var fileList = $('#multiupload').prop("files");
$('#uploadsts').html('');
var i
for ( i = 0; i < fileList.length; i++) {
$('#uploadsts').append('<p class="upload-page">'+fileList[i].name+'<span class="loading-prep" id="prog'+i+'"></span></p>');
if(i == fileList.length-1){
    uploadajax(fileList.length-1,0);
}
}

});

</script>

PHP

PHP

upload.php
    move_uploaded_file($_FILES["upload_image"]["tmp_name"],$_FILES["upload_image"]["name"]);

回答by Shreyas

Html Code

html代码

<div class="row">
    <form id="singleUploadForm" name="singleUploadForm" style="float: right; padding-right: 25px">
        <input style="float: left;" id="singleFileUploadInput" type="file" name="files" class="file-input btn btn-default" required multiple/>
        <button style="float: left" type="submit" class="btn .btn-primary">Upload</button>
    </form>
</div>

JavaScript Code

JavaScript 代码

$('#mutipleUploadForm').submit(function (event) {
    var formElement = this;
    var formData = new FormData(formElement);
    $.ajax({
        type: "POST",
        enctype: 'multipart/form-data',
        url: "/uploadFile",
        data: formData,
        processData: false,
        contentType: false,
        success: function (response) {
            alert("Image Uploaded Successfully");

            location.reload();
        },
        error: function (error) {
            console.log(error);
            // process error
        }
    });
    event.preventDefault();
});

Spring Controller Class

弹簧控制器类

@PostMapping("/uploadFile")
@ResponseBody
public boolean uploadMutipleFiles(@RequestParam("file") MultipartFile[] file) {
    List<Boolean> uploadStatusList = new ArrayList<>();
    for (MultipartFile f : file) {
        uploadStatusList.add(uploadFile(f));
    }
    return !uploadStatusList.contains(false);
}

public boolean uploadFile(@RequestParam("file") MultipartFile file) {
    boolean uploadStatus = galleryService.storeFile(file);
    return uploadStatus;
}

Spring Service Class

Spring 服务类

public boolean storeFile(MultipartFile file) {
    boolean uploadStatus = false;
    try {
        String fileName = file.getOriginalFilename();
        InputStream is = file.getInputStream();
        Files.copy(is, Paths.get(imagesDirectory + fileName), StandardCopyOption.REPLACE_EXISTING);
        System.out.println("File store success");
        uploadStatus = true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return uploadStatus;
}