如何使用ExpressJS将多个远程图片流式传输到zip文件并将其流式传输到浏览器?

4

我有一个使用ExpressJs构建的小型Web应用程序,允许公司内部人员浏览产品信息。最近有一个功能需求,要求用户能够下载一批图像(潜在地每次可能有数百个)。这些图像存储在另一台服务器上。

理想情况下,我认为需要将文件批次流式传输到zip文件中,并将其作为下载流式传输到最终用户的浏览器中。最好不必在服务器上存储文件。我的想法是尽可能减少服务器负载。

是否可能实现这个功能,或者我需要考虑另一种方法?我已经在尝试使用“request”模块进行初始下载。

如果任何人可以指引我正确的方向或推荐任何可能有帮助的NPM模块,将非常感谢。

谢谢。

1个回答

4

其中一个有用的模块是archiver,但我相信还有其他模块可供选择。

以下是一个示例程序,它展示了:

  • 如何获取URL列表(我使用async处理请求,并限制同时进行的HTTP请求数量为3);
  • 如何将这些URL的响应添加到ZIP文件中;
  • 如何在某个地方流式传输最终的ZIP文件(在本例中是标准输出,但在Express的情况下,您可以将其发送到响应对象)。

示例:

var async    = require('async');
var request  = require('request');
var archiver = require('archiver');

function zipURLs(urls, outStream) {
  var zipArchive = archiver.create('zip');

  async.eachLimit(urls, 3, function(url, done) {
    var stream = request.get(url);

    stream.on('error', function(err) {
      return done(err);
    }).on('end', function() {
      return done();
    });

    // Use the last part of the URL as a filename within the ZIP archive.
    zipArchive.append(stream, { name : url.replace(/^.*\//, '') });
  }, function(err) {
    if (err) throw err;
    zipArchive.finalize().pipe(outStream);
  });
}

zipURLs([
  'http://example.com/image1.jpg',
  'http://example.com/image2.jpg',
  ...
], process.stdout);

请注意,尽管此方法不要求图像文件被本地存储,但它确实在内存中完全构建ZIP文件。可能有其他ZIP模块可以解决这个问题,但据我所知,ZIP文件格式并不适合流式传输,因为它依赖于元数据附加到文件末尾。

嘿@robertklep,你确定这部分它确实在内存中完全构建ZIP文件吗?如果是这种情况,有没有一种方法可以在不使用太多内存的情况下实际流式传输? - Mu-Majid
@Mu-Majid 我不太确定了,你需要进行一些测试来查看在将更多文件附加到存档对象时内存使用是否会增加。 - robertklep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接