0

背景信息:我正在使用 .Net 框架和 MVC。

这是我的困境:我目前正在使用一项服务来打开一组文件(来自 sql server)。从服务中打开整个文件所需的时间与文件大小成正比,存在延迟。我正在获取此文件,然后将其从我的网络应用程序流式传输到网络浏览器。正如您可以想象的那样,这不是非常可扩展的,因为浏览器对任何超过 500MB 的文件都会超时(因为在开始流式传输之前需要很长时间)。所以我们使用的解决方案称为数据的“分块”。我从服务中获取 64KB 的数据,然后立即将它们流式传输到浏览器。

这对于单个文件非常有效,但是,我们要求如果有多个文件,则需要将它们压缩为单个文件。压缩的问题是我需要先从服务中下载所有文件,然后才能开始流式传输压缩包。我想我知道这个问题的答案,但我还是会问:有没有办法在压缩一组文件时流式传输它们?我非常怀疑您是否可以,因为压缩算法需要能够看到整个文件。或者,是否有一个 JAVASCRIPT 包可以单独捕获文件(因为它们正在流式传输),然后在流式传输完成后压缩它们?我将不胜感激任何建议!

4

1 回答 1

1

似乎有一个用于在客户端进行压缩的包JSZip。请注意,您需要 Downloadify 才能在用户计算机上创建文件。不过,它看起来不太支持跨浏览器,而且您在客户端的 JS 中抛出的数据量可能会导致问题。

除了发送 zip 文件,您可以查看流式传输不同的存档格式,例如TAR 文件ISO 文件吗?它将只包含有关文件的元数据,然后是文件数据。

或者,您可以借用 7digital 和 Bleep 唱片音乐商店使用的解决方案,即将服务器上的文件压缩到临时目录,同时立即向用户呈现页面。该页面使用客户端的一段JS轮询服务器,直到整个文件准备好下载,然后它可以正常开始下载。

更新

我注意到,如果您从 DropBox 网站下载目录,它会立即开始下载并且不知道完整的文件大小 - 这表明它在完成创建存档之前开始下载。对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 回答