2013-11-14 58 views
3

我正在使用XMLHttpRequest(級別2)將文件上載到node.js服務器。我正在檢查服務器端的有效頭文件流。現在,如果流媒體存在任何錯誤,我想觸發取消上傳。我的XMLHttpRequest代碼非常簡單:如何手動取消服務器上的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中;在Firefox中是5次;這是否在任何地方記錄?)。

編輯:正如保羅建議:

...連接關閉接收任何狀態從服務器...

在服務器端之前,我嘗試聽的終點事件響應。

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

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

但仍然重試。我只是不在乎400.

也許有另一種取消方式而不破壞請求流?

第二個編輯:有可能結束該請求不破壞請求流:

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

但XHR還是重試請求。

回答

2

在某些情況下,如果服務器過早關閉連接,則允許客戶端重試請求,這正是Chrome在您的示例中所做的。此行爲是在HTTP 1.1 specification, 8.2.4定義:

如果HTTP/1.1客戶端發送包括請求主體的請求,但不包括一個Expect請求頭字段與「100-繼續」期望,和如果客戶端沒有直接連接到HTTP/1.1源服務器,並且客戶端在從服務器接收到任何狀態之前看到連接關閉,則客戶端應該重試該請求。

如果要取消了XMLHttpRequest,你應該聽的error事件XHR的,然後調用其abort() method,這將阻止Chrome瀏覽器重新發送請求。

+0

再次感謝您的回答。在我的情況下,問題是在7次重試後觸發「錯誤」事件。除了「進展」事件之外,根本沒有任何交流。 – chmanie

+0

即使您的Express服務器調用'req.end()'? –

+0

我仔細研究了一下。在我的情況下,我不得不使用req.destroy(),而不是req.end()出於某種原因,因爲後者沒有在req上定義。如果我在發送400之後摧毀了req,它只會再試一次(我猜是因爲延遲)。所以我試圖聽取水庫的「關閉」事件,但這絕不會發生。看到我編輯的問題。 – chmanie