I am creating an Excel file with my MVC application. Depending on a configuration setting, the file will generate requiring a password or without. I can get the file to generate perfect without. But if I implement a password, I get this error:
Excel cannot open the file '' because the file format is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.
Any help would be appreciated. Here is my code:
private void ViewExcelPackageFile(Dataset dtList, string filename)
{
//
var contenttype = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
// generate password with another function if configuration requires a password
Response.Clear();
Response.ContentType = contenttype;
Response.AddHeader("content-disposition", "attachment;filename=" + filename);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
using (var stream = new MemoryStream())
{
using (ExcelPackage package = new ExcelPackage())
{
var workbook = package.Workbook;
foreach (var data in dtList)
{
ExcelWorksheet ws = workbook.Worksheets.Add(data.TableName.Replace('/', ' '));
ws.Cells["A1"].LoadFromDataTable(data, true);
}
if (password.Length > 0)
{
package.SaveAs(stream, password);
}
else
{
package.SaveAs(stream);
}
Response.BinaryWrite(stream.ToArray());
Response.Flush();
Response.End();
}
}
}
Please correct anything I'm doing wrong, but again, if I don't apply a password, it works fine. TIA!
Try the following
if (!string.IsNullOrEmpty(password))
{
package.Encryption.Password = password;
}
And then instead of using a MemoryStream, get the bytes directly.
Response.BinaryWrite(package.GetAsByteArray());
Related
I'm having a trouble with generating a .xlsx file from a template which is placed in my project resources. First I'm creating a new ExcelPackage, then opening the template which I'm going to fill with some data - but by now I want to simply download the original xlsx template. I'm trying to get the template without any modifications and download as 'Test.xlsx'. When it's downloaded, after opening the file Excel says that it cannot open my file due to invalid format or extension. Does anyone know what I am doing wrong? When I console.log my response.data then evidently there is some binary data ( about 50kb), but excel cannot show this data properly. Here is some code:
Code from .cshtml :
generateReport(){
this.#http.post(SERVER_URL + "/Mvc/Excel/GenerateReport")
.then(response => {
var blob = new Blob([response.data], { type: 'application/ms-excel' });
var downloadUrl = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = downloadUrl;
a.download = "Test.xlsx";
document.body.appendChild(a);
a.click();
});
.catch(error => {
console.log('error ', error);
return null;
});
}
Here is my controller action:
[HttpPost]
public void GenerateReport(){
string fileName;
string strfilepath = TemplatePath + "MyTemplate.xlsx";
//TemplatePath - path from my configuration where my xlsx template is stored
using(ExcelPackage p = new ExcelPackage())
{
using(FileStream = new FileStream(strfilepath, FileMode.Open))
{
p.Load(stream);
fileName = "TestReport.xlsx";
Byte[] bin = p.GetAsByteArray();
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
Response.ContentType = "application/ms-excel";
Response.Charset = "";
Response.BinaryWrite(bin);
Response.Flush();
Response.End();
}
}
}
I think the content type should be application/vnd.ms-excel for exporting excel files.
I'm working on adding Export functionality to an existing site. I've created an Excel file, and I'm able to output it to my local directory, but when I try pushing the file to the user using Response, nothing happens. I've viewed several differnet articles and Stack questions, and none seem to be different from what I have, or work when I apply them.
Here is the code I currently have:
public void Export () {
//Create instance of the database
ExportContext eDB = new ExportContext();
var query = (from x in eDB.EMPLOYEES
select x);
IEnumerable<EMPLOYEES> employees = query.ToList();
//Set filename to Table + date/time
string fileName = "EMPLOYEES" + DateTime.Now.ToShortTimeString() + ".xlsx";
//Create excel package
ExcelPackage excel = new ExcelPackage();
var worksheet = excel.Workbook.Worksheets.Add("Employees");
worksheet.Cells[1, 1].LoadFromCollection(employees, true);
using (var memoryStream = new MemoryStream()) {
//Output the file to the user via download
Response.Buffer = false;
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
excel.SaveAs(memoryStream);
memoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.Close();
Response.End();
}
}
Any help will be appreciated. Thanks.
I have tried the below coding for generating excel file on serverside.
C# CODING:
public void ReadandOpenExcel(DirectoryInfo outputDir)
{
//FileInfo newFile = new FileInfo(outputDir.FullName + #"\New Microsoft Excel Worksheet.xlsx");
var ExistFile = Server.MapPath("~/excelsample.xlsx");
var File = new FileInfo(ExistFile);
using (ExcelPackage package = new ExcelPackage(File))
{
package.Load(new FileStream(ExistFile, FileMode.Open));
ExcelWorksheet workSheet = package.Workbook.Worksheets["Sheet1"];
workSheet.Cells["A8"].Value = "kevin";
package.Save();
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", "attachment; filename=ProposalRequest.xslx");
**Response.BinaryWrite(package.GetAsByteArray());**
// myMemoryStream.WriteTo(Response.OutputStream); //works too
Response.Flush();
Response.Close();
}
}
While running the above code i got an error as : " Package object was closed and disposed, so cannot carry out operations on this object or any stream opened on a part of this package."
ERROR On This Line:
Response.BinaryWrite(package.GetAsByteArray());
Make some way for this coding to move on.
Thanks in advance.
Does it work if you get the bytes before you do the Save ?
Byte[] bin = package.GetAsByteArray();
package.Save();
And then use that value in the Binarywrite;
Response.BinaryWrite(bin);
Maybe it is getting closed on the .Save() call ?
When I try to generate an Excel file using EPPlus, Excel give me the following error message:
Excel cannot open the file 'myfilename.xlsx' because the file format or file extension is not valid. Verify the the file has not been corrupted and that the file extension matches the format of the file.
Here's my code:
public ActionResult Index()
{
using (ExcelPackage package = new ExcelPackage())
{
// I populate the worksheet here. I'm 90% sure this is fine
// because the stream file size changes based on what I pass to it.
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
var cd = new System.Net.Mime.ContentDisposition
{
Inline = false,
FileName = fileName
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(stream, contentType, fileName);
}
}
Any idea what I'm doing wrong?
All you need to do is reset the stream position. stream.Position = 0;
You shouldn't write directly to the Response, it's not the MVC way. It doesn't follow the correct MVC pipeline and it tightly couples your controller action code to the Response object.
When you add a file name as the 3rd parameter in File(), MVC automatically adds the correct Content-Disposition header... so you shouldn't need to add it manually.
The short of it is, this is what you want:
public ActionResult Index()
{
using (ExcelPackage package = new ExcelPackage())
{
// I populate the worksheet here. I'm 90% sure this is fine
// because the stream file size changes based on what I pass to it.
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
stream.Position = 0;
return File(stream, contentType, fileName);
}
}
Your code doesn't show stream being written to the HttpResponse - presumably being done in the File method which you haven't posted.
One way that does work is the following:
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader(
"content-disposition", String.Format(CultureInfo.InvariantCulture, "attachment; filename={0}", fileName));
Response.BinaryWrite(package.GetAsByteArray());
Response.End();
Similar to Joe's answer, I still had to call Response.ClearHeaders():
protected void btnDownload_Click(object sender, EventArgs e)
{
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Sample2");
ws.Cells["A1"].Value = "Sample 2";
ws.Cells["A1"].Style.Font.Bold = true;
var shape = ws.Drawings.AddShape("Shape1", eShapeStyle.Rect);
shape.SetPosition(50, 200);
shape.SetSize(200, 100);
shape.Text = "Sample 2 outputs the sheet using the Response.BinaryWrite method";
Response.Clear();
Response.ClearHeaders();
Response.BinaryWrite(pck.GetAsByteArray());
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=Sample2.xlsx");
Response.End();
}
In my application I'm uploading a file which has Swedish characters in file name. It works fine.
But when I try to download it, I get an error: "An invalid character was found in the mail header" ..Could you help regarding this
Please see my code
public ActionResult Download(Guid id)
{
var attachment = AttachmentService.GetAttachmentById(id);
var cd = new ContentDisposition
{
FileName = Utility.GetCleanedFileName(((FileAttachment)attachment).FileName),
Inline = false,
};
var file = File("\\App_Data" +((FileAttachment)attachment).FilePath, "Application");
Response.ClearHeaders();
Response.Clear();
Response.ContentType = file.ContentType;
Response.AppendHeader("Content-Disposition", cd.ToString());
var filePath = "\\App_Data" + ((FileAttachment) attachment).FilePath;
Response.WriteFile(filePath);
Response.End();
return file;
}
Please try to encode the filename using HttpUtility.UrlPathEncode.
http://msdn.microsoft.com/en-us/library/system.web.httputility.urlpathencode.aspx