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));
问题是 – 这有多可靠? 我猜这个callback会在文件被下载后调用,对吗? 但是,如果有人提供1 GB的文件的URL,那就太晚了。 我的应用程序将首先下载这个1 GB的文件只是为了检查(在callback),这是太大了。
我也在想好的旧的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
标题,并观察数据stream,确保它不超出限制。
要做到这一点,我首先对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); } });
使用请求模块观察传入数据大小的技巧是在响应中绑定到data
事件(如您正在考虑使用http
模块),然后再开始将其传输到文件stream。 如果数据大小超过最大文件大小,请调用响应的abort()
方法。