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');