XHR中止不会停止文件上传

时间:2016-06-03 17:19:13

标签: javascript file-upload xmlhttprequest abort

我已经制作了一个带有进度条的基于XHR的文件上传器,我想在完全上传之前添加一项功能来取消上传。 简化的代码(在DOM准备好后运行):

var xhr;

$('#upload').click(function(){
    var file = $('#file').get(0).files[0];
    xhr = new XMLHttpRequest();
    xhr.upload.onprogress = function(event){
        if (event.lengthComputable){
            var percent = event.loaded / event.total;
            $('#uploadpercent').html(Math.round(percent * 100) + "%");
        }
    };
    xhr.abort = function(){
        console.log('aborted');
    };
    xhr.onload = function(){
        $('#uploadpercent').html("100%");
        // ...
    };
    xhr.open("POST", "upload.php?filename=" + file.name);
    xhr.send(file);
});

$('#cancel').click(function(){
    xhr.abort();
});

在调用xhr.abort()之后,中止事件处理程序将'aborted'打印到控制台,但它不会执行任何其他操作。进度条不会停止,完成后会上传整个文件。测试了最新的Firefox和Chrome。

我无法弄清楚我的代码有什么问题。

修改

我尝试过与jQuery相同的代码: (主要来自How can I upload files asynchronously?

var jqXHR;

$('#upload').click(function(){
    var file = $('#file').get(0).files[0];
    jqXHR = $.ajax({
        type : "POST",
        url : "upload.php?filename=" + file.name,
        data : file,
        xhr: function(){
            var myXhr = $.ajaxSettings.xhr();
            if (myXhr.upload){
                myXhr.upload.addEventListener('progress', function(event){
                    if (event.lengthComputable){
                        var percent = event.loaded / event.total;
                        $('#uploadpercent').html(Math.round(percent * 100) + "%");
                    }
                }, false);
            }
            return myXhr;
        },
        success : function(response){
            $('#uploadpercent').html("100%");
            if (response.length > 0){
                console.log(response);
            }
        },
        error : function(_jqXHR, textStatus){
            if (textStatus === "abort"){
                console.log('aborted');
            }
        },
        cache : false,
        contentType : false,
        processData : false
    });
});

$('#cancel').click(function(){
    jqXHR.abort();
});

令我惊讶的是,这是按预期工作的。调用jqXHR.abort()时,也会打印“已中止”文本,进程停止,并且只上传了部分文件。 问题是我希望将来能够使我的代码独立于jquery,而且我还不明白为什么我的代码工作方式不同。

4 个答案:

答案 0 :(得分:2)

好的,我注意到事件名称是onabort。使用xhr.abort = ...行我覆盖了中止函数。所以解决方案:

xhr.onabort = function(){...};

xhr.addEventListener("abort", function(){...});

答案 1 :(得分:0)

我一直在搜索论坛,发现很多解决方案都失败了......除了Ivan Tsai的回应。

abort方法将触发服务器上的错误处理程序和请求对象的中止事件,但不会停止上传。

在收到中止事件后,我没有成功停止从服务器上传。以下都失败了:

request.pause();
request.socket.end();
request.connection.end();
request.destroy();

response.status(413).send(message);
response.end();

我发现停止上传的唯一有效方法是HTMLFormElement.reset()方法。有趣的是,调用类型文件的输入的reset方法将不起作用,但是单个输入可以包装在单个表单元素中,例如下面的uploadForm,以实现期望的效果。

var formData = new FormData(uploadForm),
    files = fileInput.files,
    xhr;

if(files) {
   for (var i = 0, stop = files.length; i < stop; i++) {
       formData.append(files[i].name, files[i]);
   }

   xhr = new XMLHttpRequest();
   xhr.open('POST', uploadForm.getAttribute('action'), true);
   progressListener = xhr.upload.addEventListener("progress", progressHandler, true);
   xhr.upload.addEventListener("abort", abortHandler, true);
   xhr.send(formData);
}

abortButton.addEventListener(function(){
    if(xhr){
        xhr.abort();
    }
    uploadForm.reset();
});

答案 2 :(得分:0)

您也可以使用 window.location.reload() 重新加载页面,或者您可以使用 window.location.href = UrlOfNewPage 切换到另一个页面。

如果这不起作用,请检查您用来取消上传的函数是否会被执行,例如输出带有 console.log 的内容

答案 3 :(得分:-1)

我有同样的问题。

XMLHttpRequest.abort()停止通知XMLHttpRequest.uplad.progress

XMLHttpRequest.abort()无法停止Chrome(63.0.3239.132)上传文件。

我尝试使用上传1G文件formObject.reset()并且它可以正常工作。

调用formObject.reset()后,Windows任务管理器中的网络使用率降至零。

<script>
function cancelUploadFile() {
  document.getElementById("my_form").reset();
}
</script>

<form id="my_form" method="post" enctype="multipart/form-data">
  <div class="w3-grey"  style="height:24px;width:0%" hidden 
id="progressBar"></div>
  <input type="file" id="file1" name="file1">
  <input type="submit" value="Upload" onclick="uploadFile()">
  <input type="submit" value="Cancel" onclick="cancelUploadFile()">
</form>