save the excel file from memory stream in NPOI - c#

I'm trying to save/download the .xlsx file that derive from memory stream like this way
public CustomObj SaveExcelFile(string sheetName)
{
var ret = new CustomObj();
MemoryStream memStream = new MemoryStream();
using (memStream = new MemoryStream())
{
IWorkbook workbook = new XSSFWorkbook();
ISheet sheet = workbook.CreateSheet(sheetName);
...
workbook.Write(memStream);
byte[] buffer = memStream.ToArray();
HttpContext.Current.Response.ContentType = "application/xlsx";
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=MyFile.xlsx");
HttpContext.Current.Response.BinaryWrite(buffer);
HttpContext.Current.Response.End();
}
return ret;
}
once I click the save file, this is supposed to download the file, but its doesn't give any error or save file. what did I miss here ?

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

c#- Corrupt file when writing to Response

I am trying to write a file to the output response stream using ASP.Net. When I download the file, I get a Errors were found opening .zip file. You can extract files from this archive, but other programs may not be able to open it. Do you want to try fixing the problems? error. I am however able to cancel this and open the zip file correctly.
What could I be doing wrong?
ASP.Net\C# code:
var pathToFile = "c:\abc.zip";
string fileName = Path.GetFileName(pathToFile);
byte[] buffer;
using (var fileStream = new FileStream(pathToFile, Filemode.open))
{
buffer = new byte[fileStream. Length];
fileStream.Read(buffer, 0, (int)fileStream.Length);
}
Response.Clear();
Response.Buffer = true;
Response.AppendHeader("content-disposition", string.Format(#"attachment; filename={0}.zip", filename));
Response.ContentType = "application/zip";
Response.AppendHeader("content-length", buffer.Length.ToString());
Response.WriteFile(pathToFile);
If you want to use buffer and write file to user, do not use Response.WriteFile.
Change to Response.OutputStream.Write, and modify your codes, like this:
var pathToFile = "c:\abc.zip";
string fileName = Path.GetFileName(pathToFile);
byte[] buffer = new byte[0];
using (var fileStream = new FileStream(pathToFile, FileMode.Open, FileAccess.Read))
{
buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, buffer.Length);
}
Response.Clear();
Response.AppendHeader("content-disposition", string.Format(#"attachment; filename={0}", filename));
Response.ContentType = "application/zip";
Response.OutputStream.Write(buffer, 0, buffer.Length);
Response.Flush();
Response.End();

How to password protect an excel generated from a byte[]?

I have the data that has to be loaded to an excel file in a byte array and I need to apply password protection on that.
I have tried converting byte[] to datatable/list and tried applying password protection using Excelpackage but I am not able to correctly convert data in byte[] array to any form.My file is getting downloaded but with some weired data. Can anyone please share your knowledge?
response.Clear();
response.Buffer = true;
response.ContentEncoding = System.Text.Encoding.UTF8;
response.ContentType = mimeType;
response.AddHeader("content-disposition", "attachment;filename="
+ Uri.EscapeDataString(fileName));
response.Charset = "";
response.Cache.SetCacheability(HttpCacheability.NoCache);
DataTable dt;
MemoryStream stream;
using (stream = new MemoryStream(fileBytes))
{
BinaryFormatter bin = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
dt = (DataTable)formatter.Deserialize(stream);
stream.Close();
}
using (ExcelPackage pack = new ExcelPackage())
{
ExcelWorksheet ws = pack.Workbook.Worksheets.Add("heelo");
ws.Cells["A1"].LoadFromDataTable(dt, true);
pack.Save("123");
var ms = new System.IO.MemoryStream();
pack.SaveAs(ms);
ms.WriteTo(HttpContext.Current.Response.OutputStream);
ms.Close();
}
response.Flush();
response.End();
Having a little trouble following you code. Why is response mime type a PDF? I think you would want that to be
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Does response actually have anything to do with the MemoryStreams since I see no reference from one to the other?
In any event, if you have the ExcelPackage available and you want to write to a Stream with a password, you can just call the overload:
pack.SaveAs(ms, "MyPassword")
Here is some more info: Password Protected Excel Download using EPPLUS

Downloading files in asp.net using C#

How do i download a file in asp.net?
here is what i did to upload it:
I upload the file into the website and saved the url to it in a database like this:
string CVPath = null;
if (uploadfiles.HasFile)
{
string file = uploadfiles.FileName;
uploadfiles.PostedFile.SaveAs(Server.MapPath(".") + "//CV//" + file);
CVPath = "~//ProfileImages//" + file;
FileName.InnerText = file;
}
else
CVPath = "";
and then I save the "CVPath" in a database
To download a file, first you need to read all the contents to a string.
MemoryStream ms = new MemoryStream();
TextWriter tw = new StreamWriter(ms);
tw.WriteLine("YourString");
tw.Flush();
byte[] bytes = ms.ToArray();
ms.Close();
Response.Clear();
Response.ContentType = "application/force-download";
Response.AddHeader("content-disposition", "attachment; filename=file.txt");
Response.BinaryWrite(bytes);
Response.End();

C# return memory stream from OpenXML resulting to a corrupted word file

I have a problem with a MemoryStream from OpenXML. I succeed with opening a Word file, changing it and downloading it through the HttpResponse if I do all the steps in a single method.
But if I try to do it in two different classes (or methods) by returning the MemoryStream, I get a corrupted word file. I thought about a flushing or buffer problem but I don't find a solution.
Here is the working code :
public void FillTemplateOpenXmlWord(HttpResponse response)
{
string filePath = #"c:\template.docx";
byte[] filebytes = File.ReadAllBytes(filePath);
using (MemoryStream stream = new MemoryStream(filebytes))
{
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(stream, true))
{
// do some changes
...
myDoc.MainDocumentPart.Document.Save();
}
string docx = "docx";
response.Clear();
response.ClearHeaders();
response.ClearContent();
response.AddHeader("content-disposition", "attachment; filename=\"" + docx + ".docx\"");
response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
response.ContentEncoding = Encoding.GetEncoding("ISO-8859-1");
stream.Position = 0;
stream.CopyTo(response.OutputStream);
response.End();
}
}
Here is the non-working code :
public void OpenFile(HttpResponse response)
{
MemoryStream stream = this.FillTemplateOpenXmlWord();
string docx = "docx";
response.Clear();
response.ClearHeaders();
response.ClearContent();
response.AddHeader("content-disposition", "attachment; filename=\"" + docx + ".docx\"");
response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
response.ContentEncoding = Encoding.GetEncoding("ISO-8859-1");
stream.Position = 0;
stream.CopyTo(response.OutputStream);
response.End();
}
public MemoryStream FillTemplateOpenXmlWord()
{
string filePath = #"c:\template.docx";
byte[] filebytes = File.ReadAllBytes(filePath);
using (MemoryStream stream = new MemoryStream(filebytes))
{
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(stream, true))
{
// do some changes
...
myDoc.MainDocumentPart.Document.Save();
}
return stream;
}
}
Any idea ?
thank you
Here's what I'm using for generating OpenXML files from memory stream. In this case it makes XLSX file from template on server, but it should be similar for other OpenXml formats.
Controller action:
public class ExportController : Controller
{
public FileResult Project(int id)
{
var model = SomeDateModel.Load(id);
ProjectExport export = new ProjectExport();
var excelBytes = export.Export(model);
FileResult fr = new FileContentResult(excelBytes, "application/vnd.ms-excel")
{
FileDownloadName = string.Format("Export_{0}_{1}.xlsx", DateTime.Now.ToString("yyMMdd"), model.Name)
};
return fr;
}
}
// Helper class
public class ProjectExport
{
private WorkbookPart workbook;
private Worksheet ws;
public byte[] Export(SomeDateModel model)
{
var template = new FileInfo(HostingEnvironment.MapPath(#"~\Export\myTemplate.xlsx"));
byte[] templateBytes = File.ReadAllBytes(template.FullName);
using (var templateStream = new MemoryStream())
{
templateStream.Write(templateBytes, 0, templateBytes.Length);
using (var excelDoc = SpreadsheetDocument.Open(templateStream, true))
{
workbook = excelDoc.WorkbookPart;
var sheet = workbook.Workbook.Descendants<Sheet>().First();
ws = ((WorksheetPart)workbook.GetPartById(sheet.Id)).Worksheet;
sheet.Name = model.Name;
// Here write some other stuff for setting values in cells etc...
}
templateStream.Position = 0;
var result = templateStream.ToArray();
templateStream.Flush();
return result;
}
}
looks like stream is closing when you return. it is in a using block. wouldn't that close the memory stream as soon as the filltemplate procedure ends?
The answer posted by gashac does not describe the issues you are going to get by not calling dispose on a stream.
Not disposing a memory stream causes memory leaks (same as a "using clause").
Memory streams keeps data in memory whereas file streams keeps data on the hdd.
Solution:
Save the memory stream into a byte array, dispose the memory stream and return the bytearray.
How to return bytearray instead stream
See the following thread to return a file as a bytearray:
HttpResponseMessage Content won't display PDF

Categories

Resources