11

我只需要使用节点 js 脚本来实现以下设置(即时生成 zip,而无需触摸磁盘并响应客户端下载)。有人可以指导和发布您的工作脚本。我试过谷歌搜索,似乎我们可以通过 zipstream 实现它。但没有找到任何示例/工作脚本。

  1. 从根文件夹中获取与 *.xml 文件匹配的文件。

  2. 立即将 http 标头写入客户端的 http 响应,说明这是下载,文件名为 .zip。

  3. zipstream 写入 zip 容器的标头字节。

  4. 创建对 S3 中第一个图像的 http 请求。

  5. 通过管道将其导入 zipstream(我们实际上不需要运行 deflate,因为图像已经被压缩)。

  6. 将其通过管道传输到客户端的 http 响应中。

  7. 对每个图像重复,zipstream 为每个文件正确写入信封。

  8. zipstream 为 zip 容器写入页脚字节

  9. 结束 http 响应。

谢谢,

斯里尼瓦斯

4

1 回答 1

17

我有同样的要求......来自 Amazon S3 的流文件,动态压缩它们(在内存中)并通过 node.js 传送到浏览器。我的解决方案涉及使用knox归档程序包并将归档的字节传输到结果流。

由于这是动态的,因此您不会知道生成的存档大小,因此您不能使用“Content-Length”HTTP 标头。相反,您必须使用“Transfer-Encoding: chunked”标头。

“分块”的缺点是您不会获得下载进度条。我尝试将 Content-Length 标头设置为近似值,但这仅适用于 Chrome 和 Firefox;IE 损坏文件;尚未使用 Safari 进行测试。

var http = require("http");
var knox = require("knox");
var archiver = require('archiver');


http.createServer(options, function(req, res) {

    var zippedFilename = 'test.zip';


    var archive = archiver('zip');
    var header = {
        "Content-Type": "application/x-zip",
        "Pragma": "public",
        "Expires": "0",
        "Cache-Control": "private, must-revalidate, post-check=0, pre-check=0",
        "Content-disposition": 'attachment; filename="' + zippedFilename + '"',
        "Transfer-Encoding": "chunked",
        "Content-Transfer-Encoding": "binary"
    };


    res.writeHead(200, header);
    archive.store = true;  // don't compress the archive
    archive.pipe(res);

    client.list({ prefix: 'myfiles' }, function(err, data) {
        if (data.Contents) {

            var fileCounter = 0;
            data.Contents.forEach(function(element) {

                var fileName = element.Key;
                fileCounter++;

                client.get(element.Key).on('response', function(awsData) {
                    archive.append(awsData, {name: fileName});

                    awsData.on('end', function () {
                        fileCounter--;

                        if (fileCounter < 1) {
                            archive.finalize();
                        }
                    });

                }).end();
            });

            archive.on('error', function (err) {
                throw err;
            });

            archive.on('finish', function (err) {
                return res.end();
            });

        }
    }).end();
}).listen(80, '127.0.0.1');
于 2014-05-06T17:37:23.823 回答