是否可以将一组文件流式传输到浏览器,因为它们正在被压缩或让客户端压缩它们?

时间:2013-07-11 16:12:53

标签: .net file browser compression streaming

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

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

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

1 个答案:

答案 0 :(得分:1)

在客户端JSZip似乎有一个用于压缩的包。请注意,您需要Downloadify然后在用户的计算机上创建该文件。虽然它看起来并不支持跨浏览器,但是在客户端上使用JS的数据量可能会导致问题。

您可以查看不同的归档格式,例如a TAR fileISO file,而不是发送zip文件吗?它只包含有关文件的元数据,然后包含文件数据。

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

更新

我注意到如果你从DropBox网站下载一个目录,它会立即开始下载并且不知道完整的文件大小 - 这表明它在完成创建存档之前就开始下载了。进一步阅读zip file formatDEFLATE algorithm表明,您可以在获得服务的完整文件数据之前开始生成压缩数据并将其流式传输到客户端。

代码看起来类似于以下未经测试和简化的示例:(使用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文件也有一个没有压缩引擎的普通存储机制,如果您不关心带宽,它会更容易。