从流创建Zip文件和下载它 [英] Creating Zip file from stream and downloading it

查看:349
本文介绍了从流创建Zip文件和下载它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我想将其转换为XML,然后压缩它,使用DotNetZip的DataTable。最终用户可以通过网页Asp.Net下载它。
我的code以下

I have a DataTable that i want to convert it to xml and then zip it, using DotNetZip. finally user can download it via Asp.Net webpage. My code in below

    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文件是空的。

the xml file in zip file is empty.

推荐答案

2的事情。首先,如果你保持code设计你有,你需要将它写入进场前对MemoryStream的执行SEEK()。

2 things. First, if you keep the code design you have, you need to perform a Seek() on the MemoryStream before writing it into the entry.

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); 
}

即使你保留这个设计,我会建议使用一个()子句,因为我已经表明,和所有的 DotNetZip范例,代替调用Dispose()的。该使用()子句是失败的脸更可靠。

Even if you keep this design, I would suggest a using() clause, as I have shown, and as described in all the DotNetZip examples, in lieu of calling Dispose(). The using() clause is more reliable in the face of failures.

现在你可能会想,为什么它是必要的,将MemoryStream寻求调用的AddEntry()之前?究其原因,的AddEntry()旨在支持那些谁传递一个流,其中的位置是非常重要的来电。在这种情况下,呼叫者需要从该流,使用流的当前位置的读出的条目数据。的AddEntry()支持。因此,设置在调用的AddEntry()前的数据流中的位置。

Now you may wonder, why is it necessary to seek in the MemoryStream before calling AddEntry()? The reason is, AddEntry() is designed to support those callers who pass a stream where the position is important. In that case, the caller needs the entry data to be read from the stream, using the current position of the stream. AddEntry() supports that. Therefore, set the position in the stream before calling AddEntry().

不过,更好的选择是修改code使用<一个href=\"http://cheeso.members.winisp.net/DotNetZipHelp/html/633c4280-51ca-cc82-b5b5-86bbe9b2e947.htm\">overload那接受WriteDelegate 的AddEntry()。它被用于添加数据集成zip文件而设计的。您原来的code写入数据到内存流,然后寻求在流,流的内容写入到拉链。它的速度更快,更容易,如果你写一次数据,这是什么WriteDelegate允许你做。在code是这样的:

But, the better option is to modify your code to use the overload of AddEntry() that accepts a WriteDelegate. It was designed specifically for adding datasets into zip files. Your original code writes the dataset into a memory stream, then seeks on the stream, and writes the content of the stream into the zip. It's faster and easier if you write the data once, which is what the WriteDelegate allows you to do. The code looks like this:

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); 
}

这直接写入数据集成zip文件的COM pressed流。非常有效!没有双缓冲。匿名委托调用在ZipFile.Save()的时间。只有一个写(COM + preSS)执行。

This writes the dataset directly into the compressed stream in the zipfile. Very efficient! No double-buffering. The anonymous delegate is called at the time of ZipFile.Save(). Only one write (+compress) is performed.

这篇关于从流创建Zip文件和下载它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆