在asp.net中向客户端导出大量数据

5

我需要通过Web向用户导出一个大量的数据(~100MB)从SQL表。如何做到最好?一个想法是将数据导出到数据库服务器上的一个文件夹中,通过某种方式对其进行压缩,然后为用户提供下载链接。还有其他方法吗?另外,我们可以在SQL Server内部压缩数据吗?

欢迎尝试任何方法。


你的目标格式是什么?最终用户会下载什么?XML?CSV?实际的SQL Server数据库文件? - Nate
一个Excel文件/CSV文件。两种格式都可以。 - Sirpingalot
5个回答

4

即使对于高速用户,我也不会让数据库等待用户下载100Mb的文件。当用户请求文件时,请他们指定一个电子邮件地址。然后调用异步进程来提取数据,将其写入临时文件(毕竟不希望内存中有超过100MB的文件),然后将临时文件压缩到存储位置,最后发送一封带有下载链接的电子邮件给用户。


我唯一需要补充的是清理老旧文件的必要性(即,定期删除那些大于100MB的文件);这可以通过一个简单的脚本和计划任务来轻松完成。而且不要忘记告诉用户,文件仅在有限的时间内可用。 - ewbi

3
您可以使用文件响应页面请求:
Response.AddHeader("Content-Disposition", 
    "attachment; filename=yourfile.csv");
Response.ContentType = "text/plain";

一定要关闭缓冲,这样在构建第二部分时,IIS可以开始发送文件的第一部分:

Response.BufferOutput = false;

之后,您可以像这样开始编写文件:

Response.Write("field1,field2,field3\r\n");

当文件完全写入后,结束响应,这样 ASP.NET 就不会将网页附加到您的文件中。
Response.End();

这样,您就不必在 Web 服务器上编写文件,只需在内存中创建文件并将其发送给用户即可。
如果需要压缩,可以以同样的方式编写 ZIP 文件。这是一个很好的 免费库 来创建 ZIP 文件。

注意:如果数据库和最终用户之间没有缓冲,那么在整个行集发送完毕之前,该过程将一直持有锁。如果只是执行READ COMMITTED操作,锁的数量可能不会很多,但仍然会存在一些锁。例如,这将阻止任何尝试升级的写入者获取表锁。对于高速终端用户来说可能还好,但在慢速连接上可能会非常糟糕。 - ahains
+1 Response.BufferOutput是一个很好的“快速修复”方案。我仍然认为@Goblyn27的解决方案是更“正确”的方法,但当你时间紧迫且用户需要立即获得报告时,禁用输出缓冲区会非常有效。 - Pandincus

0

下载链接是一个完全有效和合理的解决方案。另一个解决方案是自动将用户重定向到该文件,以便他们不需要点击链接。这真的取决于您的工作流程和UI体验。

我建议不要在SQL Server引擎中实现压缩。相反,请查看DotNetZip库(或System.IO.Conpression,如果您认为您的用户有解压缩gzip存档的能力),并在Web应用程序中实现压缩。


0
如果XML可行,一种方法是像这样选择数据“FOR XML”: http://www.sqljunkies.ddj.com/Article/296D1B56-8BDD-4236-808F-E62CC1908C4E.scuk 然后将原始XML直接作为内容类型:text/xml输出到浏览器。还要确保在具有XML扩展名的文件上设置Gzip压缩在您的Web服务器上。 http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/502ef631-3695-4616-b268-cbe7cf1351ce.mspx?mfr=true

这将缩小XML文件的大小,使其传输时只有1/3或1/4。因为XML文件存在固有的浪费空间,所以这不是最高性能的选项,但很多取决于最终需要的格式。

另一个选择是使用免费的CSharpZipLib将XML(或任何您想要的格式)压缩成用户将下载的zip文件。如果这是经常使用的东西,那么您可能需要考虑进行缓存并将zip文件存储在Web服务器上,并设置某种过期时间,以便它不会为每个请求重新生成。


0

你的方法很好。如果你需要多次执行此操作,SSIS + 7zip可能会有用于自动化处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接