c# - DotNetZip open zip file from MemoryStream - c#

What I like to do is instead of storing a zip file on disk, I like to open it up from a MemoryStream.
I am looking at the documentation for DotNetZip programming example:
Note that I tweaked it slightly based on what I thought may be needed.
var ms = new MemoryStream();
using (ZipFile zip = new ZipFile())
{
zip.AddFile("ReadMe.txt");
zip.AddFile("7440-N49th.png");
zip.AddFile("2008_Annual_Report.pdf");
zip.Save(ms); // this will save the files in memory steam
}
// now what I need is for the zip file to open up so that
the user can view all the files in it. Not sure what to do next after
zip.Save(ms) for this to happen.

Try this:
public ActionResult Index()
{
var memoryStream = new MemoryStream();
using (var zip = new ZipFile())
{
zip.AddFile("ReadMe.txt");
zip.AddFile("7440-N49th.png");
zip.AddFile("2008_Annual_Report.pdf");
zip.Save(memoryStream);
}
memoryStream.Seek(0, 0);
return File(memoryStream, "application/octet-stream", "archive.zip");
}

If this is local. you will need to save the stream in to the file and call Process.Start on it.
If this is on server. Just write your ms into Response with appropriate mime type.

You'd have to send the content of the memory stream back as the response:
using (MemoryStream ms = new MemoryStream())
{
using (ZipFile zip = new ZipFile())
{
zip.AddFile("ReadMe.txt");
zip.AddFile("7440-N49th.png");
zip.AddFile("2008_Annual_Report.pdf");
zip.Save(ms); // this will save the files in memory steam
}
context.Response.ContentType = "application/zip";
context.Response.AddHeader("Content-Length", ms.Size);
context.Response.AddHeader("Content-disposition", "attachment; filename=MyZipFile.zip");
ms.Seek(0, SeekOrigin.Begin);
ms.WriteTo(context.Response.OutputStream);
}

Try creating an ActionResult a bit like this:
I'm not 100% sure about the line var fileData = ms; and i don't have access to a dev environment just now, but there should be enough for you to work it out.
public ActionResult DownloadZip()
{
using (MemoryStream ms = new MemoryStream())
{
using (ZipFile zip = new ZipFile())
{
zip.AddFile("ReadMe.txt");
zip.AddFile("7440-N49th.png");
zip.AddFile("2008_Annual_Report.pdf");
zip.Save(ms); // this will save the files in memory steam
}
byte[] fileData = ms.GetBuffer();// I think this will work. Last time I did it, I did something like this instead... Zip.CreateZip("LogPosts.csv", System.Text.Encoding.UTF8.GetBytes(csv));
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "Whatever.zip",
// always prompt the user for downloading, set to true if you want
// the browser to try to show the file inline
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(fileData, "application/octet-stream");
}
}

this way we can write zip to output stream. may help
ZipFile zip = new ZipFile();
List<Attachment> listattachments = email.Attachments;
int acount = attachments.Count;
for (int i = 0; i < acount; i++)
{
zip.AddEntry(attachments[i].FileName, listattachments[i].Content);
}
Response.Clear();
Response.BufferOutput = false;
string zipName = String.Format("{0}.zip", message.Headers.From.DisplayName);
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "attachment; filename=" + zipName);
zip.Save(Response.OutputStream);
Response.End();

Related

Returning a zipfile from a web api

I have built an asp net web api. I need to return a zipfile, as a result of some inner logic. I'm using this code and it works, but the resulting zip file, when unzipped manually, gave me this error "There are data after the end of the payload"
using (ZipFile zip = new ZipFile())
{
...
zip.Save(di.FullName + "\\" + "Update.zip");
}
string path = Path.Combine(Properties.Settings.Default.PathDisposizioniHTML, "Update.zip");
var response = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new System.IO.FileStream(path, System.IO.FileMode.Open);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
This is how i receive the data in a .net console application:
using (Stream output = File.OpenWrite(#"C:\prova\MyFile.zip"))
using (Stream input = httpResponse.GetResponseStream())
{
input.CopyTo(output);
}
If you already have the zip file on your system, you shouldn't need to do anything special before sending it as a response.
This should work:
string filePath = #"C:\myfolder\myfile.zip";
return File(filePath, "application/zip");
If you're making the file on the fly, i.e. getting other files and programatically putting them into a zip file for the user, the following should work:
public IActionResult GetZipFile(){
//location of the file you want to compress
string filePath = #"C:\myfolder\myfile.ext";
//name of the zip file you will be creating
string zipFileName = "zipFile.zip";
byte[] result;
using (MemoryStream zipArchiveMemoryStream = new MemoryStream())
{
using (ZipArchive zipArchive = new ZipArchive(zipArchiveMemoryStream, ZipArchiveMode.Create, true))
{
ZipArchiveEntry zipEntry = zipArchive.CreateEntry(zipFileName);
using (Stream entryStream = zipEntry.Open())
{
using (MemoryStream tmpMemory = new MemoryStream(System.IO.File.ReadAllBytes(filePath)))
{
tmpMemory.CopyTo(entryStream);
};
}
}
zipArchiveMemoryStream.Seek(0, SeekOrigin.Begin);
result = zipArchiveMemoryStream.ToArray();
}
return File(result, "application/zip", zipFileName);
}
This is taken from a recent ASP.NET project of my own.

How to download multiple files stored in database as bytes

I am storing files in database in the form of bytes. We have requirement to download all attachments as zip file. Please suggest
Try this
protected void ZipDownload()
{
var list = //query for getting the files.
ZipFile zip = new ZipFile();
foreach (var file in list)
{
zip.AddEntry(file.docname, (byte[])file.doc.ToArray());
}
var zipMs = new MemoryStream();
zip.Save(zipMs);
byte[] fileData = zipMs.GetBuffer();
zipMs.Seek(0, SeekOrigin.Begin);
zipMs.Flush();
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=docs.zip ");
Response.ContentType = "application/zip";
Response.BinaryWrite(fileData);
Response.End();
}

Adding multiple files to an in memory zip archive in c#

I'm trying to use the Zip Archive library in .NET 4.5 to create a .zip file in memory of a bunch of byte[] attachments:
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
string zipFilename = string.Format(#"c:\temp\{0} - {1}.zip",
"test",
System.DateTime.Now.ToString("yyyyMMddHHmm"));
using (var fileStream = new FileStream(zipFilename, FileMode.Create))
{
foreach (var attachment in attachments)
{
ZipArchiveEntry entry = archive.CreateEntry(attachment.FileName);
using (Stream ZipFile = entry.Open())
{
byte[] data = attachment.Data;
ZipFile.Write(data, 0, data.Length);
}
}
}
}
}
PdfAttachment is a class with a byte[] Data and string Filename.
My problem is twofold. Once, the zip archive is empty. 2, rather than save it to a file, I'd like to use the response outputs to download the file in the users browser, which I have tried with:
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}.zip; size={1}", "test.zip", memoryStream.Length));
Response.BinaryWrite(memoryStream);
Response.Flush();
Response.End();
I haven't been able to find many examples online, hence the vagueness.
The fileStream is never written to because it is not associated with the archive.
So the archive is being written to the memoryStream.
BinaryWrite only accepts a byte[] so use memoryStream.ToArray().
Also, Response.ContentType value is wrong.

ZipOutputStream generates corrupted zip file when zipenty is numerous

I have the code below to simulate an action i am trying to perform using SharpZipLib. The generated zip file runs well when the limit of 'i' is low. But as 'i' tends towards a high value e.g 100, the generated zip file is corrupted. When I repair it, it opens okay. Is there any mistake i am making. Thanks.
using(MemoryStream memoryStream = new MemoryStream())
using (ZipOutputStream zipOutputStream = new ZipOutputStream(memoryStream))
{
zipOutputStream.SetLevel(3);
for (int i = 1; i < 10; i++)
{
ZipEntry zipEntry = new ZipEntry("Test" + i.ToString() + ".xlsx");
zipEntry.DateTime = DateTime.Now;
zipOutputStream.PutNextEntry(zipEntry);
using (Stream inputStream = File.OpenRead(#templatePath))
{
StreamUtils.Copy(inputStream, zipOutputStream,
new byte[inputStream.Length]);
inputStream.Close();
zipOutputStream.CloseEntry();
}
}
zipOutputStream.IsStreamOwner = false;
zipOutputStream.Close();
memoryStream.Position = 0;
WorkbookUtil.StreamFileToBrowser("Report.Zip", memoryStream.GetBuffer());
}
WorkbookUtil.StreamFileToBrowser is my static method to download files to the user browser
Update:
This is the Method for downloading to Browser
public static void StreamFileToBrowser(string sFileName, byte[] fileBytes)
{
System.Web.HttpContext context = System.Web.HttpContext.Current;
context.Response.Clear();
context.Response.ClearHeaders();
context.Response.ClearContent();
context.Response.AppendHeader("content-length", fileBytes.Length.ToString());
context.Response.ContentType = GetMimeTypeByFileName("application/zip");
context.Response.AppendHeader("content-disposition", "attachment; filename=" + sFileName);
context.Response.BinaryWrite(fileBytes);
context.ApplicationInstance.CompleteRequest();
}

ZipStorer - Zip Text in MemoryStream, Transmit through httpResponse, unable open as Zip File

Note: I have solved the problem myself. See the below answer.
I'm using ZipStorer to zip files in ASP.NET C# 4.0 WebForm.
After I created the Zip in MemoryStream and transmitted it using httpResponse, the client user was unable to open the file as a Zip File.
Any tips? Thanks.
Below is my code:
string text = GetLongText();
byte[] ba = Encoding.UTF8.GetBytes(text);
using (MemoryStream ms = new MemoryStream())
{
using (ZipStorer zip = ZipStorer.Create(ms, "My Zip File"))
{
zip.AddStream(ZipStorer.Compression.Deflate, "MyText.txt", new MemoryStream(ba), DateTime.Now, "My Text");
Response.Clear();
Response.AppendHeader("content-disposition", "attachment; filename=MyZip.zip");
Response.ContentType = "application/zip";
ms.WriteTo(Response.OutputStream);
Response.End();
}
}
I have solve the problem myself. Below is the codes:
string text = GetLongText();
byte[] ba = Encoding.UTF8.GetBytes(text);
using (MemoryStream ms = new MemoryStream())
{
using (ZipStorer zip = ZipStorer.Create(ms, "My Zip"))
{
zip.AddStream(ZipStorer.Compression.Deflate, "text.txt", new MemoryStream(ba), DateTime.Now, "My Text");
}
Response.AppendHeader("content-disposition", "attachment; filename=MyZip.zip");
Response.ContentType = "application/zip";
Response.BinaryWrite(ms.ToArray());
Response.End();
}
}

Categories