4

XMLHttpRequest (レベル 2) を使用して、ファイルを node.js サーバーにアップロードしています。サーバー側で有効なヘッダーのファイルストリームをチェックしています。ストリーミング中にエラーが発生した場合、アップロードのキャンセルをトリガーしたいと考えています。私の XMLHttpRequest コードは非常に単純です。

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);
});

サーバー側では、バリデーターを介して req ストリームをファイル ストリームにパイプしています。検証中にエラーが発生した場合、XMLHttpRequest がアップロードを中止するようにします。しかし、リクエストへのレスポンスとして 400 を送信するだけではまったく機能しません。あらゆる種類のリスナーを xhr に登録しましたが、どれも起動しませんでした。400 をまったく気にしていないようで、ファイルをアップロードしようとします。通常、この機会に onreadystatechange イベントが発生することを期待します。

req.end() を発行して req を閉じようとしましたが、それは少し厳しいようで、別の好奇心が明らかになります。これを行うと、XMLHttpRequest は POST リクエストの送信を正確に 7 回再試行します (Chrome では 5 回、Firefox では 5 回。これはどこかに文書化されていますか?)。

編集:ポールが提案したように:

...サーバーからステータスを受信する前に接続を閉じます...

サーバー側では、応答の終了イベントをリッスンしようとします。

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

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

しかし、とにかく再試行します。400にしか興味ない

リクエストストリームを破壊せずにキャンセルする別の方法があるでしょうか?

2 番目の編集: リクエスト ストリームを破棄せずにリクエストを終了することが可能です。

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

しかし、XHR はまだリクエストを再試行しています。

4

2 に答える 2

4

状況によっては、サーバーが途中で接続を閉じると、クライアントはリクエストを再試行できます。これは、Chrome が例で行っていることです。この動作は、HTTP 1.1 仕様 8.2.4で定義されています。

HTTP/1.1 クライアントがリクエスト本文を含むが、"100-continue" 期待値を持つ Expect リクエスト ヘッダー フィールドを含まないリクエストを送信する場合、およびクライアントが HTTP/1.1 オリジン サーバーに直接接続されていない場合、およびクライアントがサーバーからステータスを受信する前に接続が閉じていることを確認した場合、クライアントはリクエストを再試行する必要があります。

XMLHttpRequest をキャンセルするerror場合は、XHR のイベントをリッスンしてからabort()メソッドを呼び出す必要があります。これにより、Chrome がリクエストを再送信するのを防ぐことができます。

于 2013-11-14T10:53:55.563 に答える