从stream中创buildZip文件并下载
我有一个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文件是空的。
2件事。 首先,如果您保留了代码devise,则需要先在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); }
即使你保留这个devise,我也会build议一个using()子句,正如我所示,并且如所有DotNetZip示例中所述 ,代替调用Dispose()。 using()子句在失败时更可靠。
现在你可能会想,为什么在调用AddEntry()之前需要在MemoryStream中寻找? 原因是,AddEntry()被devise为支持那些通过位置是重要的stream的调用者。 在这种情况下,调用者需要使用stream的当前位置从stream中读取条目数据。 AddEntry()支持。 因此,在调用AddEntry()之前在stream中设置位置。
但是,更好的select是修改代码以使用接受WriteDelegate的AddEntry()的重载 。 它是专门为将数据集添加到zip文件而devise的。 您的原始代码将数据集写入内存stream,然后在stream上寻找,并将stream的内容写入压缩文件。 如果您只写一次数据,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); }
这将数据集直接写入压缩文件中的压缩stream。 非常高效! 没有双缓冲。 匿名委托在ZipFile.Save()时被调用。 只执行一次写入(+压缩)。
你为什么不closuresMemoryStream,我将它包装在一个using子句中,对于zipFile也可以zipFile ? 此外,我还假设是一个DataTable …放入错误检查,看看是否有行,请参阅下面的代码…
dt.TableName =“声明”;
if(dt.Rows!= null && dt.Rows.Count> = 1){
使用(MemoryStream stream = new MemoryStream()){
dt.WriteXml(stream);
//感谢Cheeso / Mikael
stream.Seek(0,SeekOrigin.Begin);
//
使用(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);
zipFile.Save(stream);
//评论这一点
/ *
回复于(zipstream); // <-----这是从哪里来的?
* /
}
回复于(stream);
}
}
//没有行...不要打扰...
编辑:再次看了这个,并意识到从Codeplex的Ionic.Ziplib被使用,我稍微改变了代码,而不是zipFile.Save(Response.OutputStream); 我用zipFile.Save(stream); 使用MemoryStream类的stream实例并使用Response.Write(stream);将其写出Response.Write(stream); 。
编辑#2:感谢Cheeso + Mikael指出了这个明显的缺陷 – 我错过了一英里的路程,直到我意识到这个stream是在最后才知道他们的意见。
希望这有助于,最好的问候,汤姆。
你有没有尝试冲洗之前压缩stream?
dt.WriteXml(stream); stream.Flush(); ZipFile zipFile = new ZipFile();
好。 看起来好像我们在这里变得很远,所以你需要开始更多的debugging。
更新你的代码来执行以下操作:
dt.WriteXml(stream); stream.Seek(0, SeekOrigin.Begin); File.WriteAllBytes("c:\test.xml", stream.GetBuffer());
看看你是否有一个有效的XML文件。 如果你这样做,那么继续前进你的ZipFile。 将其保存到本地文件。 看看它是否存在,有你的XML文件,你的XML文件中有内容。
如果是这样的话,试着回应一下内存stream作为回应,看看是否有效。
那么你应该能够进一步追踪问题。
添加一个ContentType标头:
Response.ContentType = "application/zip";
这将允许浏览器检测您发送的内容。
仔细检查你正在返回的stream。 在你的例子下面
zipFile.Save(Response.OutputStream); Response.Write(zipstream); zipFile.Dispose();
您正在使用Save方法将zipFile保存到您的响应stream中,但是您也使用zipstreamvariables调用Response.Write()。 什么是zipstream? 检查它是不是一个空的stream。
此代码将帮助您从stream中下载文件。
using (var outStream = new MemoryStream()) { using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true)) { var fileInArchive = archive.CreateEntry("FileName.pdf", CompressionLevel.Optimal); using (var entryStream = fileInArchive.Open()) using (WebResponse response = req.GetResponse()) { using (var fileToCompressStream = response.GetResponseStream()) { fileToCompressStream.CopyTo(entryStream); } } } using (var fileStream = new FileStream(@"D:\test.zip", FileMode.Create)) { outStream.Seek(0, SeekOrigin.Begin); outStream.CopyTo(fileStream); } }
命名空间需求:
using System.IO.Compression; using System.IO.Compression.ZipArchive;
从stream中创build一个zip文件并下载。 下面是代码。
FileStream stream=File.OpenRead(@"D:\FileDownLoad\DeskTop\1.txt"); MemoryStream MS=new MemoryStream(); ZipOutputStream zipOutputStream = new ZipOutputStream(MS); zipOutputStream.SetLevel(9); ZipEntry entry = new ZipEntry("1.txt"); zipOutputStream.PutNextEntry(entry); byte[] buffer = new byte[stream.Length]; int byteRead = 0; while ((byteRead = stream.Read(buffer, 0, buffer.Length)) > 0) zipOutputStream.Write(buffer, 0, byteRead); zipOutputStream.IsStreamOwner = false; stream.Close(); zipOutputStream.Close(); MS.Position = 0; Response.ContentType = "application/application/octet-stream"; Response.AppendHeader("content-disposition", "attachment; filename=\"Download.zip\""); Response.BinaryWrite(MS.ToArray());
- 驻留在App_Code中的类不可访问
- 什么是IIS应用程序池?
- 将所有的第一个字母转换为大写,每个单词都要低一些
- MVC2中的Html.Partial(view,model)和Html.RenderPartial(view,model)之间有什么区别(如果有的话)?
- 什么是“_vti_cnf”,“_vti_pvt”,“_vti_script”和“_vti_txt”文件夹?
- appSettings vs applicationSettings。 appSettings过时了吗?
- 如何将水晶报表绑定到手动创build的数据集
- 调用wkhtmltopdf从HTML生成PDF
- 通过jQuery调用ASP.NET服务器端的方法