我有一个DataTable,我想将其转换为XML,然后使用DotNetZip将其压缩.最后,用户可以通过ASP.NET网页下载. 我的代码在下面

    dt.TableName = "Declaration";

    MemoryStream stream = new MemoryStream();
    dt.WriteXml(stream);

    ZipFile zipFile = new ZipFile();
    zipFile.AddEntry("Report.xml", "", stream);
    Response.ClearContent();
    Response.ClearHeaders();
    Response.AppendHeader("content-disposition", "attachment; filename=Report.zip");

    zipFile.Save(Response.OutputStream);
    //Response.Write(zipstream);
    zipFile.Dispose();

zip文件中的xml文件为空.

推荐答案

两件事.首先,如果保留现有的代码设计,则需要在将MemoryStream写入条目之前对其执行Seek().

dt.TableName = "Declaration"; 

MemoryStream stream = new MemoryStream(); 
dt.WriteXml(stream); 
stream.Seek(0,SeekOrigin.Begin);   // <-- must do this after writing the stream!

using (ZipFile zipFile = new ZipFile())
{
  zipFile.AddEntry("Report.xml", "", stream); 
  Response.ClearContent(); 
  Response.ClearHeaders(); 
  Response.AppendHeader("content-disposition", "attachment; filename=Report.zip"); 

  zipFile.Save(Response.OutputStream); 
}

即使您保留这种设计,我也建议使用using()子句,正如我所展示的,以及所有DotNetZip examples条中所描述的,来代替调用Dispose().using()子句在遇到故障时更可靠.

现在您可能会想,为什么在调用AddEntry()之前需要在MemoryStream中查找?原因是,AddEntry()旨在支持那些通过位置重要的流的调用方.在这种情况下,调用者需要从流using the current position of the stream中读取条目数据.AddEntry()支持这一点.因此,在调用AddEntry()之前设置流中的位置.

但是,更好的 Select 是修改代码以使用overload of AddEntry() that accepts a WriteDelegate.它是专门为将数据集添加到zip文件而设计的.原始代码将数据集写入内存流,然后在该流上搜索,并将流的内容写入zip.如果只写一次数据,就会更快更容易,WriteDelegate允许您这样做.代码如下所示:

dt.TableName = "Declaration"; 
Response.ClearContent(); 
Response.ClearHeaders(); 
Response.ContentType = "application/zip";
Response.AppendHeader("content-disposition", "attachment; filename=Report.zip"); 

using(Ionic.Zip.ZipFile zipFile = new Ionic.Zip.ZipFile())
{
    zipFile.AddEntry("Report.xml", (name,stream) => dt.WriteXml(stream) );
    zipFile.Save(Response.OutputStream); 
}

这会将数据集直接写入zipfile中的压缩流.非常高效!没有双缓冲.匿名委托在ZipFile.Save()时调用.仅执行一次写入(+压缩).

Asp.net相关问答推荐

如何在 ASP.Net Core 中验证上传的文件

检测 ASP.NET 中的内存泄漏

asp.net 单选按钮分组

jQuery隐藏字段

.NET 站点如何隐藏其文件的 .aspx 扩展名?

System.Web.Helpers.Crypto - 盐在哪里?

判断会话是否为空

如何从网页 (asp.net) 启动 EXE

在 RedirectToAction 调用中传播 QueryString 参数

如何在不使用 Session 的情况下在 ASP.net 中的页面之间传递值

System.Web.HttpContext 无法识别

使用 jQuery 调用 ASP.NET PageMethod/WebMethod - 返回整个页面

C# 7 本地函数未按预期工作且未显示错误

svg 无法在 localhost 上的 IIS 网络服务器上运行

HttpResponse.End 或 HttpResponse.Close 与 HttpResponse.SuppressContent

捕获的异常本身为 null !

主机与 DnsSafeHost

ASP.NET MVC NonAction 含义

将 HTML 字符串转换为图像

如何使用 int ID 列更改 ASP.net Identity 2.0 的表名?