如何手动取消服务器上的 XMLHttpRequest 文件上传(流) [英] How do I manually cancel a XMLHttpRequest file upload (stream) on the server

查看:78
本文介绍了如何手动取消服务器上的 XMLHttpRequest 文件上传(流)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 XMLHttpRequest(级别 2)将文件上传到 node.js 服务器.我正在检查服务器端的有效标头的文件流.现在,如果流式传输时出现任何错误,我想触发取消上传.我的 XMLHttpRequest 代码很简单:

var xhr = new XMLHttpRequest();var 文件;$('#file').on('change', function(e) {文件 = this.files[0];file.filename = this.files[0].name;});$('#submit').on('click', function(e) {e.preventDefault();xhr.open('POST', '/upload', true);xhr.send(文件);});

在服务器端,我通过验证器将 req 流传输到文件流中.如果验证时发生任何错误,我希望 XMLHttpRequest 中止上传.但是仅仅发送 400 作为对请求的响应根本不起作用.我向 xhr 注册了各种侦听器,但没有一个触发.它似乎根本不关心 400 并且仍然尝试上传文件.通常我希望 onreadystatechange 事件会在这种情况下触发.

我尝试通过发出 req.end() 来关闭请求,但这似乎有点苛刻,并揭示了另一种好奇心.如果我这样做,XMLHttpRequest 会重试发送 POST 请求 7 次(在 Chrome 中;在 Firefox 中 5 次;是否有任何记录?).

正如保罗所建议的:

<块引用>

...在从服务器接收任何状态之前连接关闭...

在服务器端,我尝试监听响应的完成事件.

 checkedFile.on('error', function (err) {res.status(400);重发();});res.on('完成', 函数 () {req.destroy();});

但它还是会重试.我只是不在乎 400.

也许还有另一种取消方式而不破坏请求流?

第二次可以在不破坏请求流的情况下结束请求:

checkedFile.on('wrong', function (err) {checkFile.end();res.writeHead(400, { 'Connection': 'close' });重发();});

但 XHR 仍在重试请求.

解决方案

在某些情况下,如果服务器过早关闭连接,则允许客户端重试请求,这就是 Chrome 在您的示例中所做的.此行为在 HTTP 1.1 规范 8.2.4:

<块引用>

如果 HTTP/1.1 客户端发送的请求包含请求正文,但不包含具有100-continue"期望的 Expect 请求标头字段,并且客户端未直接连接到 HTTP/1.1 原始服务器,如果客户端在从服务器接收到任何状态之前看到连接关闭,客户端应该重试请求.

如果你想取消 XMLHttpRequest,你应该监听 XHR 的 error 事件,然后调用它的 abort() 方法,这将阻止 Chrome 重新发送请求.>

I am using XMLHttpRequest (Level 2) to upload a file to a node.js server. I am checking the file-stream for the valid header on the server side. Now I want to trigger a cancellation of the upload if there are any errors while streaming. My XMLHttpRequest code is very simple:

var xhr = new XMLHttpRequest();
var file;
$('#file').on('change', function(e) {
  file = this.files[0];
  file.filename = this.files[0].name;
});
$('#submit').on('click', function(e) {
  e.preventDefault();
  xhr.open('POST', '/upload', true);
  xhr.send(file);
});

On the server side I am piping the req stream through my validator into a file stream. I want the XMLHttpRequest to abort the upload if any errors occur while validating. But just sending a 400 as response to the request doesn't work at all. I registered all kinds of listeners to the xhr but none of them fire. It doesn't seem to care about the 400 at all and still tries to upload the file. Normally I would expect that the onreadystatechange event would fire on this occasion.

I tried closing the req by issuing an req.end() but that seems a bit harsh and reveals another curiosity. If I do that, the XMLHttpRequest retries to send the POST request exactly 7 times (in Chrome; 5 times in Firefox; is this documented anywhere?).

Edit: As Paul suggested:

...connection close before receiving any status from the server...

On the server side I try to listen to the finish event of the response.

  checkedFile.on('error', function (err) {
    res.status(400);
    res.end();
  });

  res.on('finish', function () {
    req.destroy();
  });

But it retries anyway. I just doesn't care about the 400.

Maybe there is another way of canceling without destroying the request stream?

Second edit: It is possible to end the request without destroying the request stream:

checkedFile.on('wrong', function (err) {
  checkedFile.end();
  res.writeHead(400,  { 'Connection': 'close' });
  res.end();
});

But the XHR is still retrying the request.

解决方案

Under some circumstances, if the server prematurely closes the connection, then the client is allowed to retry requests, which is what Chrome is doing in your example. This behavior is defined in the HTTP 1.1 specification, 8.2.4:

If an HTTP/1.1 client sends a request which includes a request body, but which does not include an Expect request-header field with the "100-continue" expectation, and if the client is not directly connected to an HTTP/1.1 origin server, and if the client sees the connection close before receiving any status from the server, the client SHOULD retry the request.

If you want to cancel the XMLHttpRequest, you should listen on the errorevent of the XHR and then call its abort() method, which will prevent Chrome from re-sending the request.

这篇关于如何手动取消服务器上的 XMLHttpRequest 文件上传(流)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆