首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从流创建Zip文件并下载

从流创建Zip文件并下载
EN

Stack Overflow用户
提问于 2010-02-15 21:29:08
回答 7查看 83K关注 0票数 50

我有一个DataTable,我想把它转换成xml,然后使用DotNetZip压缩它。最后,用户可以通过Asp.Net网页下载它。我的代码如下

代码语言:javascript
复制
    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文件为空。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-02-16 01:32:47

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

代码语言:javascript
复制
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()子句来代替调用Dispose(),正如我已经展示过的,并且在所有DotNetZip examples中都有描述。在失败的情况下,using()子句更可靠。

现在您可能想知道,为什么在调用AddEntry()之前必须在MemoryStream中查找?原因是,AddEntry()被设计为支持那些在位置很重要的地方传递流的调用者。在这种情况下,调用方需要使用流的当前位置从流中读取条目数据。AddEntry()支持这一点。因此,请在调用AddEntry()之前设置流中的位置。

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

代码语言:javascript
复制
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()时被调用。仅执行一次写入(+压缩)。

票数 71
EN

Stack Overflow用户

发布于 2010-02-15 22:13:15

你有没有试过在拉链之前冲掉小溪?

代码语言:javascript
复制
dt.WriteXml(stream);
stream.Flush();
ZipFile zipFile = new ZipFile();
票数 1
EN

Stack Overflow用户

发布于 2010-02-15 23:12:24

好的。看起来我们还没有走到这一步,所以你需要多调试一下。

更新您的代码以执行以下操作:

代码语言:javascript
复制
dt.WriteXml(stream);
stream.Seek(0, SeekOrigin.Begin);
File.WriteAllBytes("c:\test.xml", stream.GetBuffer());

看看您是否有一个有效的XML文件。如果你这样做了,那么继续对你的ZipFile做同样的事情。将其保存到本地文件。看看它是否在那里,是否有您的xml文件和xml文件中的内容。

如果这样做有效,试着只发送回内存流作为响应,看看是否有效。

然后,您应该能够进一步跟踪问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2266204

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档