Creating a zip file from a stream and loading it

I have a DataTable that I want to convert to xml and then zip using DotNetZip. finally, the user can download it through the Asp.Net web page. My code is 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(); 

The xml file in the zip file is empty.

+43
c # stream zip dotnetzip
Feb 15 '10 at 13:29
source share
8 answers

2 things. First, if you save the code that you have, you need to execute Seek () on a MemoryStream before writing it to a record.

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

Even if you save this project, I would suggest the use () sentence, as I showed, and as described in all the DotNetZip examples instead of calling Dispose (). The using () clause is more robust in case of failures.

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

But the best option is to modify your code to use the AddAntry () overload, which accepts WriteDelegate . It was designed specifically for adding datasets to zip files. Your source code writes the data set to the memory stream, then searches for the stream and writes the contents of the stream to zip. It is faster and easier if you write data once, which allows WriteDelegate. The code is as follows:

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

This writes the data set directly to the compressed stream in a zip file. Very effective! No double buffering. An anonymous delegate is called during ZipFile.Save (). Only one recording is performed (+ compression).

+64
Feb 15 '10 at 17:32
source share

Why didn’t you close the MemoryStream, I would wrap this in a using clause, can the same be said about zipFile ? Also, dt I assume this is a DataTable ... puts in error checking to see if there are any rows, see the code below ...

     dt.TableName = "Declaration"; 

     if (dt.Rows! = null && dt.Rows.Count> = 1) {
       using (MemoryStream stream = new MemoryStream ()) {
          dt.WriteXml (stream); 

          // Thanks Cheeso / Mikael
          stream.Seek (0, SeekOrigin.Begin);
          //

          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); 
              zipFile.Save (stream);

              // Commented this out
              / *
                Response.Write (zipstream);  // <----- Where did that come from?
              * /
           }
           Response.Write (stream);
        } 
     }
     // No rows ... don't bother ...

Edit: After looking at it again and realizing that Ionic.Ziplib from Codeplex was used, I changed the code a bit, instead of zipFile.Save(Response.OutputStream); I used zipFile.Save(stream); using the stream instance of the MemoryStream class and wrote it out using Response.Write(stream); .

Edit # 2: Thanks to Cheeso + Mikael for pointing out an obvious flaw - I missed it in a mile and didn't understand their comment until I realized that the stream was at the end ...

Hope this helps, Regards, Tom.

+4
Feb 15 2018-10-15
source share

Did you try to clear the thread before it was buttoned?

 dt.WriteXml(stream); stream.Flush(); ZipFile zipFile = new ZipFile(); 
+1
Feb 15 2018-10-15
source share

Ok It seems like we are very far here, so you need to start debugging this a bit more.

Update your code to do the following:

 dt.WriteXml(stream); stream.Seek(0, SeekOrigin.Begin); File.WriteAllBytes("c:\test.xml", stream.GetBuffer()); 

See if you have a valid XML file. If you do, do the same with ZipFile. Save it in a local file. See if there is an xml file, and your xml file has content in it.

If this works, try sending back only the memory stream as an answer, see if it works.

Then you can track the problem further.

+1
Feb 15 '10 at 15:12
source share

Add ContentType Header:

 Response.ContentType = "application/zip"; 

this will allow browsers to detect what you are sending.

0
Feb 15 2018-10-15
source share

Double check the thread you are returning back. In the example below

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

You save the zipFile to the response stream using the Save method, but then you also call Response.Write () with the zipstream variable. What is zipstream? Make sure this is also an empty thread.

0
Feb 15 '10 at 14:21
source share

This code will help you download the file from the 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); } } 

Required Namespace:

 using System.IO.Compression; using System.IO.Compression.ZipArchive; 
0
Dec 17 '15 at 12:15
source share

Creating a zip file from a stream and downloading it. Below is the code.

 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()); 
0
Sep 04 '16 at 17:17
source share



All Articles