最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I manually cancel a XMLHttpRequest file upload (stream) on the server - Stack Overflow

programmeradmin4浏览0评论

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.

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.

Share Improve this question edited Nov 14, 2013 at 14:55 chmanie asked Nov 14, 2013 at 10:35 chmaniechmanie 5,0863 gold badges22 silver badges28 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

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.

OK it seems, one has to live with this:

What happens when no response is received for a request? I'm seeing retries

Inconsistent browser retry behaviour for timed out POST requests

http://geek.starbean/?p=393

By the way, you run into the same problems if you're checking the file header for the content-type.

发布评论

评论列表(0)

  1. 暂无评论