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

时间:2014-08-01 12:18:32

标签: javascript node.js

我想用Request库下载一个文件。它很简单:

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

您建议采用什么方法限制下载最大文件大小,而不是实际下载整个内容并检查它的大小?

2 个答案:

答案 0 :(得分:13)

我实际上会使用您已经讨论过的两种方法:检查content-legnth标题,并观察数据流以确保它不会超出您的限制。

为此,我首先向网址发出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);
    }
});

使用请求模块观察传入数据大小的技巧是在开始管道之前绑定到响应上的data事件(就像您在考虑使用http模块一样)到你的文件流。如果数据大小超过了您的最大文件大小,请调用响应的abort()方法。

答案 1 :(得分:0)

我有一个类似的问题。我现在使用提取来限制下载大小。

operatorId