Zip file shows empty on trying to extract - c#

I am using the following code to download a set of files stored in my database by putting them into a zip file:
SqlDataAdapter adp = new SqlDataAdapter("select FILE_NAME, FILE, content_type from tbl where id = " + "168", Configuration.getSQLConnString("ConnStr"));
DataTable dtFiles = new DataTable();
adp.Fill(dtFiles);
if (dtFiles.Rows.Count > 0)
{
using (var zipStream = new ZipOutputStream(Response.OutputStream))
{
foreach (DataRow dr in dtFiles.Rows)
{
byte[] bytes;
string fileName, contentType;
fileName = dr["File_Name"].ToString();
bytes = (byte[])dr["File"];
contentType = dr["Content_Type"].ToString();
Response.Clear();
Response.Buffer = true;
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.AddHeader("Content-Disposition", "attachment; filename=Files.zip");
Response.ContentType = "application/zip";
byte[] fileBytes = bytes;
ZipEntry fileEntry = new ZipEntry(ZipEntry.CleanName(fileName));
fileEntry.Size = fileBytes.Length;
zipStream.SetLevel(3);
zipStream.PutNextEntry(fileEntry);
zipStream.Write(fileBytes, 0, fileBytes.Length);
zipStream.CloseEntry();
}
zipStream.Flush();
zipStream.Close();
}
}
The zip file gets generated and is downloaded and it also shows me a size of about 2Mb but then when I extract the zip file it shows me the following error:
Can someone please point out what is that I am doing wrong?

ZipOutputStream did not help me at all; tried breaking my head over it but nothing helped. Then I came across this library called DotNetZip and here's the code to download files stored in the database into a zip file:
using (ZipFile zip = new ZipFile())
{
foreach (DataRow dr in dtResumes.Rows)
{
zip.AddEntry(dr["File_Name"].ToString(), (byte[])dr["Resume"]);
}
zip.Save("C:\\Test\\MyZipFile.zip");
}

Related

Returning ZipFile in Controller after reading bytes from database

I'm trying to read files from my database (varbinary) and add them to a zip file so that users can download all files related to a specific user.
From what I can gather, I need to read the files from the database, create the zip file, read the files into memory and then write that to the file (doing it without this returned a blank zip file).
It will save the files to the zip, but unfortunately the files are all corrupted.
public FileResult DownloadAllDocuments(int userId)
{
// File name
string ZipFilename = DateTime.Now + "_Files.zip";
// Get files from database
List<DocumentVO> Documents = DocumentDAO.DownloadAllDocuments(userId);
var zipFileMemoryStream = new MemoryStream();
using (ZipArchive archive = new ZipArchive(zipFileMemoryStream, ZipArchiveMode.Update, leaveOpen: true))
{
foreach (DocumentVO document in Documents)
{
var entry = archive.CreateEntry(document.fileName, CompressionLevel.Fastest);
using (var entryStream = entry.Open())
{
entryStream.Write(document.File, 0, document.File.Length);
}
}
}
zipFileMemoryStream.Seek(0, SeekOrigin.Begin);
return File(zipFileMemoryStream, "application/octet-stream", ZipFilename);
}
Please try these codes instead of return File line
using (MemoryStream ms = new MemoryStream())
{
zip.Save(ms);
Response.ClearHeaders();
Response.ClearContent();
Response.Charset = "";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + ZipFilename);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = "application/zip";
Response.BinaryWrite(ms.ToArray());
}

ZipArchive creates invalid zip file in list from webservices

I have a problem with get files to zip.
The web service is giving me the right files, for example www.XYP.com/GetFile?=1234 , when I open the Url, automaticly downloads the file, but after I zip this document its not correct files, which are destroyes
My code is here:
private void CreatedZipFile(Dictionary<int, string> listChecked)
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach (KeyValuePair<int, string> kvp in listChecked)
{
ZipArchiveEntry demoFile = archive.CreateEntry(kvp.Key.ToString() + kvp.Value.ToString() + ".pdf");
string strDownLoad = System.Configuration.ConfigurationManager.AppSettings["GETFILESERVICES"] + kvp.Key.ToString();
WebService control = new WebService();
var clientnew = new System.Net.WebClient().DownloadData(strDownLoad);
using (var entryStream = demoFile.Open())
{
using (StreamWriter streamWriter = new StreamWriter(entryStream))
{
streamWriter.BaseStream.Write(clientnew, 0, clientnew.Length);
streamWriter.Close();
}
}
}
}
byte[] bytesInStream = memoryStream.ToArray();
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "attachment; filename=file.zip");
Response.Buffer = true;
Response.Clear();
Response.BinaryWrite(bytesInStream);
Response.Flush();
//MemoryStream.WriteTo(Response.OutputStream); //works too
Response.End();
}
}
Thanks for help or any advice,

Zip files created by DotNetZip using ASP.NET sometimes causing network error

I'm debugging a rather odd situation involving DotNetZip and ASP.NET. Long story short, the resulting zip files that are being created by the code are being reliably downloaded by Firefox, but most other browsers are intermittently returning a Network Error. I've examined the code and it reads about as generically as anything that involves DotNetZip.
Any clues?
Thanks!
EDIT: Here's the complete method. As I mentioned, it's about as generic as it gets:
protected void btnDownloadFolders_Click(object sender, EventArgs e)
{
//Current File path
var diRoot = new DirectoryInfo(_currentDirectoryPath);
var allFiles = Directory.GetFiles(diRoot.FullName, "*.*", SearchOption.AllDirectories);
Response.Clear();
Response.BufferOutput = false;
var archiveName = String.Format("{0}-{1}.zip", diRoot.Name, DateTime.Now.ToString("yyyy-MM-dd HHmmss"));
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "inline; filename=\"" + archiveName + "\"");
using (var zip = new ZipFile())
{
foreach (var strFile in allFiles)
{
var strFileName = Path.GetFileName(strFile);
zip.AddFile(strFile,
strFile.Replace("\\" + strFileName, string.Empty).Replace(diRoot.FullName, string.Empty));
}
zip.Save(Response.OutputStream);
}
Response.Close();
}
It could be because you are not sending the content-length. I've seen errors occur in sending files to the browser where it was not specified. So create the zip file in a MemoryStream. save the stream to a Byte Array so you can send the length as a Response also. Although I can't say for sure that it will fix your specific problem.
byte[] bin;
using (MemoryStream ms = new MemoryStream())
{
using (var zip = new ZipFile())
{
foreach (var strFile in allFiles)
{
var strFileName = Path.GetFileName(strFile);
zip.AddFile(strFile, strFile.Replace("\\" + strFileName, string.Empty).Replace(diRoot.FullName, string.Empty));
}
//save the zip into the memorystream
zip.Save(ms);
}
//save the stream into the byte array
bin = ms.ToArray();
}
//clear the buffer stream
Response.ClearHeaders();
Response.Clear();
Response.Buffer = true;
//set the correct contenttype
Response.ContentType = "application/zip";
//set the filename for the zip file package
Response.AddHeader("content-disposition", "attachment; filename=\"" + archiveName + "\"");
//set the correct length of the data being send
Response.AddHeader("content-length", bin.Length.ToString());
//send the byte array to the browser
Response.OutputStream.Write(bin, 0, bin.Length);
//cleanup
Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();

Create ZipArchive in memory then download to client

I have read several blog posts and questions about this, but I can't get this working. It just downloads a corrupt ZIP archive that is <2KB. I feel like I'm missing something simple with streaming the PDF file to the Zip Archive?
using (var outStream = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
{
foreach (string Item in Items)
{
ReportParameter[] prms = new ReportParameter[1];
prms[0] = new ReportParameter("Item", Item, false);
rv.ServerReport.SetParameters(prms);
rv.ShowParameterPrompts = false;
rv.ServerReport.Refresh();
byte[] bytes = rv.ServerReport.Render("PDF", null, out mimeType, out encoding, out extension, out streamids, out warnings);
string fileName = Item + ".pdf";
var fileInArchive = archive.CreateEntry(fileName);
using (var entryStream = fileInArchive.Open())
using (var fileToCompressStream = new MemoryStream(bytes))
{
fileToCompressStream.CopyTo(entryStream);
}
}
}
outStream.Position = 0;
Response.ClearContent();
Response.ClearHeaders();
Response.AppendHeader("content-disposition", "attachment; filename=PDFReports_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip");
Response.Write(outStream);
}

C# No Data in Folder after Downloading ASP

Let me start off by saying I'm sure this is something that's quite simple, unfortunately I just can't seem to figure it out. So here's my problem, I query the database, return what I need, zip it all up, and prompt user to save. When You attempt to open this, there are no files inside the folder. Where has my data gone? I stepped through everything, and it appears to write everything properly. Any help would be greatly appreciated!!
if (e.CommandName == "DownloadAttachment")
{
e.Canceled = true;
// Create a zip and send it to the client.
//Response.Write(#"<script language='javascript'>alert('Details saved successfully')</script>");
var item = e.Item as GridEditableItem;
fileId = (int)item.GetDataKeyValue("Unique");
FileData[] allrecords = null;
using (
SqlConnection conn =
new SqlConnection(ConfigurationManager.ConnectionStrings["PtcDbModelEntities"].ConnectionString))
{
using (
SqlCommand comm = new SqlCommand("Select Unique1, BinaryData, FileName from PtcDbTracker.dbo.CafFileTable where Unique1=#fileId AND FileName IS NOT NULL", conn))
{
comm.Parameters.Add(new SqlParameter("#fileId", fileId));
conn.Open();
using (var reader = comm.ExecuteReader())
{
var list = new List<FileData>();
while (reader.Read())
{
list.Add(new FileData { Unique1 = reader.GetInt32(0) });
long len = reader.GetBytes(1, 0, null, 0, 0);
Byte[] buffer = new byte[len];
list.Add(new FileData { BinaryData = (byte)reader.GetBytes(1, 0, buffer, 0, (int)len), FileName = reader.GetString(2) });
allrecords = list.ToArray();
}
}
conn.Close();
}
}
using (var compressedFileStream = new MemoryStream())
{
//Create an archive and store the stream in memory.
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false))
{
if (allrecords != null)
{
foreach (var record in allrecords)
{
//Create a zip entry for each attachment
if (record.FileName != null)
{
var zipEntry = zipArchive.CreateEntry(record.FileName);
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(record.BinaryData))
{
using (var zipEntryStream = zipEntry.Open())
{
//Copy the attachment stream to the zip entry stream
originalFileStream.CopyTo(zipEntryStream);
}
}
}
}
}
Response.ClearContent();
Response.ClearHeaders();
Response.BinaryWrite(compressedFileStream.ToArray());
Response.AppendHeader("Content-Disposition", "Attachment; filename=result.zip");
Response.Flush();
Response.Close();
zipArchive.Dispose();
//How Do I Prompt for open or save?
}
}
Are you sure the BinaryWrite is getting a valid ByteArray?
In any case here's a tested method to output a file to the Response with the typically needed headers for binary attachments:
public bool WriteFile(byte[] byteContent, DateTime dtTimeStamp, string urlFilename)
{
HttpContext context = HttpContext.Current;
HttpResponse response = context.Response;
response.Clear();
response.ClearHeaders();
response.ClearContent();
response.BufferOutput = true;
response.AppendHeader("Content-Length", byteContent.Length.ToString());
response.AppendHeader("Content-Type", "application/octet-stream");
response.AppendHeader("Last-Modified", dtTimeStamp.ToString("R"));//Last-Modified Wed, 28 Aug 2013 10:16:46 GMT
response.AppendHeader("Content-Disposition", "inline; filename=\"" + urlFilename + "\"");
response.BinaryWrite(byteContent);
response.Flush();
// Prevents any other content from being sent to the browser
response.SuppressContent = true;
context.ApplicationInstance.CompleteRequest();
return true;
}

Categories

Resources