0

背景情報: .Net フレームワークと MVC を使用しています。

これが私のジレンマです。現在、サービスを使用して(SQLサーバーから)ファイルのグループを開いています。サービスからファイル全体を開くのにかかる時間は、ファイルのサイズに正比例します。このファイルを取得して、Web アプリから Web ブラウザーにストリーミングします。ご想像のとおり、ブラウザは約 500MB を超えるファイルに対してタイムアウトになるため、これはあまりスケーラブルではありません (ストリーミングの開始までに時間がかかりすぎるため)。したがって、私たちが使用しているソリューションは、データの「チャンキング」と呼ばれます。サービスから 64KB のデータを取得し、すぐにブラウザーにストリーミングしています。

これは 1 つのファイルに対してはうまく機能しますが、複数のファイルがある場合は、それらを 1 つのファイルに圧縮する必要があるという要件があります。圧縮の問題は、圧縮されたパッケージのストリーミングを開始する前に、サービスからすべてのファイルをダウンロードする必要があることです。この質問に対する答えはわかっていると思いますが、とにかく質問します。圧縮されているファイルのグループをストリーミングする方法はありますか? 圧縮アルゴリズムはファイル全体を表示できる必要があるため、できるとは思えません。または、ファイルを個別に (ストリーミングしているため) キャプチャし、ストリーミングが完了したら圧縮できる JAVASCRIPT パッケージはありますか? これについてアドバイスをいただければ幸いです!!

4

1 に答える 1

1

クライアント側で圧縮するためのパッケージJSZipがあるようです。ユーザーのコンピューターにファイルを作成するには、 Downloadify が必要になることに注意してください。ただし、クロスブラウザはあまりサポートされていないように見えます.クライアントのJSで投げかけているデータの量が問題を引き起こす可能性があります.

zip ファイルを送信する代わりに、TAR ファイルISO ファイルなどの別のアーカイブ形式をストリーミングすることを検討していただけますか? ファイルに関するメタデータとファイルデータのみが含まれます。

または、7digital および Bleep レコード音楽ストアで使用されているソリューションを借りることもできます。これは、サーバー上のファイルを一時ディレクトリに圧縮し、ページをユーザーにすぐに表示することです。このページは、クライアント側で JS の一部を使用して、ファイル全体をダウンロードする準備が整うまでサーバーをポーリングします。その後、通常どおりダウンロードを開始できます。

アップデート

DropBox Web サイトからディレクトリをダウンロードすると、すぐにダウンロードが開始され、完全なファイル サイズがわからないことに気付きました。これは、アーカイブの作成が完了する前にダウンロードを開始していることを示しています。zip ファイル形式DEFLATE アルゴリズムをさらに読むと、サービスから完全なファイル データを取得する前に、圧縮データの生成とクライアントへのストリーミングを開始できることが示唆されます。

コードは、次のテストされていない単純化された例のようになります: ( DotNetZipクラス名を使用)

// Get a stream to the client
using (var zipStream = ZipOutputStream(Response.OutputStream)) {

foreach (var filename in filenames) {
     // Write file header
     ZipEntry entry = new ZipEntry(filename);
     zipStream.PutNextEntry(entry);

     // Write file chunks
     byte[] chunk;
     while ((chunk = service.GetChunk(filename)).Length > 0) {
         zipStream.Write(chunk, 0, chunk.Length);
     }
}

// Write zip file directory to complete file
zipStream.Finish();

}

ファイルをさらに圧縮したい場合 (コンプレッサーにより大きなブロックを指定した場合など)、できるだけ早くデータをストリーミングしたい場合で、データがサービスからアプリケーションに送信されるよりも速く送信されることがわかっている場合アプリケーションからクライアントまで、foreach ループ内にある種の指数バッファーを実装できます。

int chunksPerWrite = 1; // Better if this is defined outside of the foreach loop
byte[] chunk;
var chunks = new List<byte[]>();
while ((chunk = service.GetChunk(filename)).Length > 0) {
     chunks.Add(chunk)

     if (chunks.Count >= chunksPerWrite) {
         // Combine all the chunks with some array copying logic not included
         byte[] megaChunk = CombineAllChunks(chunks);
         zipStream.Write(megaChunk, 0, megaChunk.Length);
         chunksPerWrite *= 2; // or chunksPerWrite++ for a linear growth
     }
}

// Cut for brevity - combine any last chunks and send to the zipStream.

ZIP仕様を読んだところ、一度に効果的に圧縮できるデータの量には制限があることが示唆されましたが、その制限が何であるかはわかりません(データに依存する可能性がありますか?)。スペックに詳しい方にお聞きしたいのですが...

何らかの理由で自分で作成する必要がある場合、Zip ファイルには圧縮エンジンのない単純なストレージ メカニズムもあり、帯域幅を気にしなければ簡単に作成できます。

于 2013-07-11T16:25:04.117 に答える