3

我了解如何使用 Node.js + 请求加载远程文件,然后我可以读取它并返回 png 二进制 blob。有没有一种优雅的方式来完成一个请求(甚至是单行)

就像是:

http.createServer(function(req, res) {
    res.writeHead(200, {
        'Content-Type': 'image/png'
    });
    var picWrite = fs.createWriteStream(local);
    var picFetch = fs.createReadStream(local);
    picStream.on('close', function() {
        console.log("file loaded");
    });
    request(remote).pipe(picWrite).pipe(picFetch).pipe(res);
})

明确一点:我的目标是从 CDN 加载远程文件,将其缓存到本地服务器,然后在原始请求中返回文件。在以后的请求中,我fs.exists()先检查它是否存在。


这是我迄今为止的最大努力:

http.createServer(function(req, res) {
    var file = fs.createWriteStream(local);
    request.get(remote).pipe(file).on('close', function() {
        res.end(fs.readFileSync(local), 'binary');
    });
})
4

1 回答 1

7

由于请求将返回一个可读流,我们可以监听它dataend事件以写入 HTTP 响应和可写流。

var http = require('http');
var request = require('request');

http.createServer(function(req, res) {
  res.writeHead(200, { 'Content-Type': 'image/png' });
  var file = fs.createWriteStream(local);

  // request the file from a remote server
  var rem = request(remote);
  rem.on('data', function(chunk) {
    // instead of loading the file into memory
    // after the download, we can just pipe
    // the data as it's being downloaded
    file.write(chunk);
    res.write(chunk);
  });
  rem.on('end', function() {
    res.end();
  });
});

您展示的方法首先将数据写入磁盘,然后再次将其读入内存。这是毫无意义的,因为数据在写入磁盘时已经可以访问。

如果您使用事件处理程序,您可以同时写入 HTTP 响应和文件流,而无需再次将文件毫无意义地加载到内存中。这也解决了 using 的问题pipe(),因为pipe()会消耗可读流中的数据,并且只能执行一次。

这也解决了内存不足的问题,因为如果您要下载一个大文件,那么它会有效地运行您的 Node.js 进程的内存不足。使用流,一次只将文件的块加载到内存中,因此您不会遇到此问题。

于 2013-10-08T01:32:37.473 回答