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 に答える