簡體   English   中英

Node.js 和 Request - 限制下載文件的文件大小

[英]Node.js and Request - limiting the file size of downloaded file

我想下載一個帶有請求庫的文件。 這很簡單:

request({
    url: url-to-file
}).pipe(fs.createWriteStream(file));

由於 URL 是由用戶提供的(在我的情況下),我想限制我的應用程序將下載的最大文件大小 - 假設為 10MB。 我可以像這樣依賴content-length標頭:

request({
    url: url-to-file
}, function (err, res, body) {
    var size = parseInt(res.headers['content-length'], 10);

    if (size > 10485760) {
        // ooops - file size too large
    }
}).pipe(fs.createWriteStream(file));

問題是 - 這有多可靠? 我想這個回調會在文件下載調用,對嗎? 但是,如果有人提供 1 GB 的文件 URL,那就太晚了。 我的應用程序將首先下載這 1 GB 的文件,只是為了檢查(在回調中)這是否太大。

我也在考慮舊 Node 的http.get()方法。 在這種情況下,我會這樣做:

var opts = {
    host: host,
    port: port,
    path: path
};

var file = fs.createWriteStream(fileName),
    fileLength = 0;

http.get(opts, function (res) {
    res.on('data', function (chunk) {
        fileLength += chunk.length;

        if (fileLength > 10485760) { // ooops - file size too large
            file.end();
            return res.end();
        }

        file.write(chunk);
    }).on('end', function () {
        file.end();
    });
});

您建議使用什么方法來限制下載最大文件大小,而無需實際下載整個文件並檢查其大小?

我實際上會使用您討論過的兩種方法:檢查content-legnth標頭,並觀察數據流以確保它不超過您的限制。

為此,我首先向 URL 發出HEAD請求,以查看content-length標頭是否可用。 如果它大於你的極限,你可以在那里停下來。 如果它不存在或小於您的限制,則發出實際的GET請求。 由於HEAD請求將只返回標頭而沒有實際內容,這將有助於快速清除具有有效content-length的大文件。

接下來,發出實際的GET請求並觀察傳入的數據大小以確保它不超過您的限制(這可以通過請求模塊完成;見下文)。 無論HEAD請求是否找到content-length標頭,您都希望這樣做,作為健全性檢查(服務器可能對content-length撒謊)。

像這樣的東西:

var maxSize = 10485760;

request({
    url: url,
    method: "HEAD"
}, function(err, headRes) {
    var size = headRes.headers['content-length'];
    if (size > maxSize) {
        console.log('Resource size exceeds limit (' + size + ')');
    } else {
        var file = fs.createWriteStream(filename),
            size = 0;

        var res = request({ url: url });

        res.on('data', function(data) {
            size += data.length;

            if (size > maxSize) {
                console.log('Resource stream exceeded limit (' + size + ')');

                res.abort(); // Abort the response (close and cleanup the stream)
                fs.unlink(filename); // Delete the file we were downloading the data to
            }
        }).pipe(file);
    }
});

使用 request 模塊觀察傳入數據大小的技巧是在開始將data到文件流之前綁定到響應上的data事件(就像您正在考慮使用http模塊一樣)。 如果數據大小超過您的最大文件大小,請調用響應的abort()方法。

我有一個類似的問題。 我現在使用fetch來限制下載大小。

const response = await fetch(url, {
    method: 'GET',t
    size: 5000000, // maximum response body size in bytes, 5000000 = 5MB 
}).catch(e => { throw e })

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM