2016-05-29 132 views
3

考慮下面的代碼:文件下載和客戶端斷開?

async function (req, res, next) { 
    const fd = await fs.open("myfile.txt") 
    fs.createReadStream(null, { fd, autoClose: false }) 
    .on('error', next) 
    .on('end',() => fs.close(fd)) 
    .pipe(res) 
} 

如果客戶端下載整個文件之前斷開,會發生什麼?即end仍然會被調用或是文件描述符泄漏,如果是的話我該如何解決它?如果調用「end」,這是否意味着即使客戶端不再監聽它,整個文件也會被讀取?

請注意,我知道我可以在沒有fd的情況下這樣做,但這是對更復雜代碼的簡化。

回答

2

它看起來像文件不會關閉,或者至少不會調用您的end事件處理程序。

您可以創建該測試,但這裏是我的:

const http = require('http'); 
const fs = require('fs'); 

var server = http.createServer(function (req, res) { 
    console.log('server request received'); 
    const fd = fs.openSync('myfile.txt', 'r'); 
    fs.createReadStream(null, { fd, autoClose: false }) 
     .on('error', err => { 
      console.error('file error', err); 
     }) 
     .on('end',() => { 
      console.log('file end'); 
      fs.close(fd); 
     }) 
     .on('close',() => { 
      console.log('file closed'); 
     }) 
     .pipe(res) 
      .on('error', err => console.error('server stream error', err)) 
      .on('end',() => console.log('server stream end')) 
      .on('close',() => console.log('server stream closed')) 
    ; 
}); 

server.listen(0, 'localhost',() => { 
    const address = server.address(); 

    var req = http.request({port: address.port}, function (res) { 
     res.on('data', data => { 
      console.log('response data'); 
      // Comment next line to read whole file. 
      req.abort(); 
     }); 
     res.on('end',() => { 
      console.log('response ended'); 
      setTimeout(() => server.close(), 1000); 
     }); 
     req.once('abort',() => { 
      console.log('request aborted'); 
     }); 
    }); 

    req.end(() => { 
     console.log('request sent'); 
    }); 
}); 

我刪除異步/等待運行測試的簡單性。

req.abort()叫,我得到以下的輸出:

request sent 
server request received 
response data 
request aborted 
response ended 
server stream closed 

評論該行,並允許代碼讀取整個文件後:

request sent 
server request received 
response data 
response data 
response data 
response data 
response data 
response data 
file end 
response data 
response ended 

來創建測試myfile.txt我用下面的命令:

dd if=/dev/zero of=myfile.txt bs=1k count=200 
+0

這實際上並不奇怪 - 一套'autoClose:fa顯式地使用'lse'並且不關閉文件。 – zerkms

+0

是的,但我認爲'autoClose'被設置爲'false'並非沒有理由 - 首先與fs.open相同,而不是像文中所述的那樣僅將文件路徑傳遞給'fs.createReadStream':「Note ,我知道我可以在沒有fd的情況下做到這一點,但這是對更復雜代碼的簡化。「 – ahwayakchih

+0

是的,我也瞭解。但在這種情況下,過度簡化導致了天真的預期結果,這並不需要任何確認:-)無論如何,我不是指你的答案,這是好的,我upvoted它:-) – zerkms