如何以小块上传带有ajax的文件并检查失败,重新上传失败的部分。

Posted

技术标签:

【中文标题】如何以小块上传带有ajax的文件并检查失败,重新上传失败的部分。【英文标题】:How to upload a file with ajax in small chunks and check for fails, re-upload the parts that failed. 【发布时间】:2016-02-05 21:17:10 【问题描述】:

我有一个用户上传的文件,我想实现以下目标。

    将文件分成大约一兆字节的小块。 上传每个块,等待它完成后再开始上传下一个块。 为每个块获取成功或失败报告。 重新上传失败的区块。 按百分比获取进度。

这里有一些粗略的 javascript。我真的迷路了。在线获取了一些代码并尝试对其进行修改。

$.chunky = function(file, name)        
                var loaded = 0;
                var step = 1048576//1024*1024;
                var total = file.size;
                var start = 0;
                var reader = new FileReader();

                reader.onload = function(e)

                var d = file:reader.result
                $.ajax(
                    url:"../record/c/index.php",
                    type:"POST", 
                    data:d).done(function(r)
                    $('.record_reply_g').html(r);

                    loaded += step;                 
                    $('.upload_rpogress').html((loaded/total) * 100);

                        if(loaded <= total)
                            blob = file.slice(loaded,loaded+step);
                            reader.readAsBinaryString(blob);
                         else 
                            loaded = total;
                        
                )              
                ;

                var blob = file.slice(start,step);
                reader.readAsBinaryString(blob);
            

我怎样才能达到上述目的。如果有可行的解决方案,请解释发生了什么。

【问题讨论】:

你试过github.com/blueimp/jQuery-File-Upload/wiki/Chunked-file-uploads 不错的开始,您需要使用累积范围进行切片,加载块大小,并且步长似乎是恒定的......一般来说,尝试将问题分解为更小的部分,就像可以从文件上传一系列数据的东西,然后是可以在文件的每个部分上调用远程上传器的部分,然后是处理错误的部分,然后是宣布“我完成了”的部分,.. . 总之,更多的小功能,少一个大的加载功能。 @dandavis 我有另一个只能做块的功能,问题是等待每个块上传。它是一个数组,每个包含大约 1mb 的块。 【参考方案1】:

我已将 afzalex 的答案修改为使用readAsArrayBuffer(),并将块作为文件上传。

    var loaded = 0;
    var reader = new FileReader();
    var blob = file.slice(loaded, max_chunk_size);
    reader.readAsArrayBuffer(blob);
    reader.onload = function(e) 
      var fd = new FormData();
      fd.append('filedata', new File([reader.result], 'filechunk'));
      fd.append('loaded', loaded);
      $.ajax(url, 
        type: "POST",
        contentType: false,
        data: fd,
        processData: false
      ).done(function(r) 
        loaded += max_chunk_size;
        if (loaded < file.size) 
          blob = file.slice(loaded, loaded + max_chunk_size);
          reader.readAsArrayBuffer(blob);
        
      );
    ;

【讨论】:

【参考方案2】:

你没有为任何块上传失败做任何事情。

$.chunky = function(file, name)        
    var loaded = 0;
    var step = 1048576//1024*1024; size of one chunk
    var total = file.size;  // total size of file
    var start = 0;          // starting position
    var reader = new FileReader();
    var blob = file.slice(start,step); //a single chunk in starting of step size
    reader.readAsBinaryString(blob);   // reading that chunk. when it read it, onload will be invoked

    reader.onload = function(e)            
        var d = file:reader.result
        $.ajax(
            url:"../record/c/index.php",
            type:"POST", 
            data:d                     // d is the chunk got by readAsBinaryString(...)
        ).done(function(r)           // if 'd' is uploaded successfully then ->
                $('.record_reply_g').html(r);   //updating status in html view

                loaded += step;                 //increasing loaded which is being used as start position for next chunk
                $('.upload_rpogress').html((loaded/total) * 100);

                if(loaded <= total)            // if file is not completely uploaded
                    blob = file.slice(loaded,loaded+step);  // getting next chunk
                    reader.readAsBinaryString(blob);        //reading it through file reader which will call onload again. So it will happen recursively until file is completely uploaded.
                 else                        // if file is uploaded completely
                    loaded = total;            // just changed loaded which could be used to show status.
                
            )              
        ;

编辑

要再次上传失败的块,您可以执行以下操作:

var totalFailures = 0;
reader.onload = function(e) 
    ....
).done(function(r)
    totalFailures = 0;
    ....
).fail(function(r)   // if upload failed
   if((totalFailure++) < 3)  // atleast try 3 times to upload file even on failure
     reader.readAsBinaryString(blob);
    else                    // if file upload is failed 4th time
      // show message to user that file uploading process is failed
   
);

【讨论】:

if(loaded reader.readAsBinaryString(blob) 被调用然后reader.onload 被再次调用。所以文件上传是递归进行的。 ohhhhh 好的,有道理,我们可以检查每个块的故障吗? 不是“var d = file:reader.result”,上传整个文件吗?不应该是“blob”,它是一个块吗? var d=file:reader.result 没有上传文件。但正在读取文件,而且只是其中的一部分。

以上是关于如何以小块上传带有ajax的文件并检查失败,重新上传失败的部分。的主要内容,如果未能解决你的问题,请参考以下文章

sh 以小块剪切给定的声音文件。对有声读物非常有用。

表值参数:以小块发送数据

如何通过ajax上传文件而不会超时?

上传大图像时网络连接中止后恢复或重新启动ajax请求?

ajax上传文件,并检查文件类型检查文件大小

大文件上的 JQuery Ajax 文件上传失败