MVC FileStreamResult is not downloading file with custom file name - c#

The pdf downloads fine but with a random name - 9619012021194536.pdf
I'm trying to set a custom name but it is not working.
The downloaded file still has a random name instead of the custom name being set in code.
public ActionResult Appointment(int id)
{
Stream stream = null;
string fileName = "";
try
{
stream = GenerateAppointmentReport(id);
fileName = id + "_" + DateTime.Now.ToString("ddMMyyyyHHmmss") + ".pdf";
}
catch (Exception ex)
{
}
return new FileStreamResult(stream, MimeMapping.GetMimeMapping(fileName))
{ FileDownloadName = fileName };
}

You can use this code:
public ActionResult Appointment(int id)
{
Stream stream = null;
string fileName = "";
try
{
stream = GenerateAppointmentReport(id);
fileName = id + "_" + DateTime.Now.ToString("ddMMyyyyHHmmss") + ".pdf";
}
catch (Exception ex)
{
}
return new FileStreamResult(stream, "binary") { FileDownloadName = fileName };
}
I used this code and the file was downloaded with the specific name I mentioned.

You can bind the data in a temporary object of type GridView and then write the object to the output stream like this:
public ActionResult Appointment(int id)
{
GridView gridview = new GridView();
gridview.DataSource = fileData; //fileData is an object with all the properties
gridview.DataBind();
Response.ClearContent();
Response.Buffer = true;
tmpfileName = id + "_" + DateTime.Now.ToString("ddMMyyyyHHmmss") + ".pdf";
Response.AddHeader("content-disposition", "attachment; filename = " + tmpfileName);
Response.ContentType = "application/pdf";
Response.Charset = "";
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
gridview.RenderControl(htw);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
}
}
return RedirectToAction("Appointment"); // To another/same action
}

Related

Unable to download Excel file when call from Postman

I am trying to download Excel file using web API but I am unable to download file in postman where as I am able to download Excel file when I enter URL in browser though while opening file I get warning message like below :
When i hit endpoint using POSTMAN then file get corrupted and it is showing junk characters.
Code :
protected virtual byte[] ExportToXlsx<T>(IEnumerable<T> itemsToExport)
{
using (var stream = new MemoryStream())
{
using (var xlPackage = new ExcelPackage())
{
// get handles to the worksheets
var worksheet = xlPackage.Workbook.Worksheets.Add(typeof(T).Name);
//create Headers and format them
var manager = new PropertyManager<T>(itemsToExport.First());
manager.WriteCaption(worksheet, SetCaptionStyle);
var row = 2;
foreach (var items in itemsToExport)
{
manager.CurrentObject = items;
manager.WriteToXlsx(worksheet, row++, false);
}
xlPackage.Save();
}
return stream.ToArray();
}
}
private readonly IServiceContext ctx;
public void Download(string guid)
{
var bytes = ExportToXlsx(list);
ctx.reqobj.HttpContext.Response.Headers.Add("Content-Disposition", "attachment; filename=\"demo.xlsx\"");
ctx.reqobj.HttpContext.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
ctx.reqobj.HttpContext.Response.Body.Write(bytes, 0, bytes.Length);
}
Note : I am using OfficeOpenXml for Excel file creation.
I will appreciate any help.
Update :
Try using "Send and download" instead of "Send"
https://www.getpostman.com/docs/v6/postman/sending_api_requests/responses
Postman doesn't download any file just return you the data that the server or your service provides. i have a project that download an excel to with the OpenXML here is an example with which you can guide with some styles to.
[HttpGet]
public void DownloadTable(int id)
{
List<Employee> all = db.Employees.Where(x => x.ManagerId == id).ToList();
String file = "Example.xlsx";
String path = Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data"), file);
List<string[]> headerRow = new List<string[]>() { new string[] { "EmployeeId", "Name", "Shift", "Timestamp" } };
string headerRange = "A2:" + Char.ConvertFromUtf32(headerRow[0].Length + 64) + "2";
ExcelPackage excel = new ExcelPackage();
excel.Workbook.Worksheets.Add("Employees");
var page = excel.Workbook.Worksheets["Employees"];
page.Cells["A1:D1"].Merge = true;
page.Cells["A1:D1"].Value = "Supervisor: " + all.FirstOrDefault().Manager + " - " + id;
page.Cells["A1:D1"].Style.Font.Bold = true;
page.Cells[headerRange].LoadFromArrays(headerRow);
int z = 3;
foreach (Reporte r in all)
{
page.Cells["A" + z].Value = r.Id;
page.Cells["B" + z].Value = r.Name;
page.Cells["C" + z].Value = r.Shift;
page.Cells["D" + z].Value = r.Timestamp;
z++;
}
page.Cells["D3:D" + z].Style.Numberformat.Format = "dddd dd MMMM YYYY";
page.Cells["A2:D2"].AutoFilter = true;
page.Cells["A1:D" + z].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
page.Cells["A1:D" + z].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
page.Cells["A2:D" + z].AutoFitColumns();
page.Cells["A1:D1"].Style.Fill.PatternType = ExcelFillStyle.Solid;
page.Cells["A1:D1"].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(1, 183, 222, 232));
FileInfo excelFile = new FileInfo(path);
excel.SaveAs(excelFile);
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition",
"attachment; filename=" + file + ";");
response.TransmitFile(path);
response.Flush();
response.End();
File.Delete(path);
}
The stream needs to be passed to the package.
Right now nothing is being given to the package,
//...
using (var xlPackage = new ExcelPackage())
//...
So nothing is being saved to the stream, which is why the error is shown when trying to open the file.
There is no need to convert the memory stream to an array. Return the stream and pass that along for the response.
protected virtual Stream ExportToXlsx<T>(IEnumerable<T> itemsToExport) {
var stream = new MemoryStream();
using (var xlPackage = new ExcelPackage(stream)) { //<<< pass stream
// get handles to the worksheets
var worksheet = xlPackage.Workbook.Worksheets.Add(typeof(T).Name);
//create Headers and format them
var manager = new PropertyManager<T>(itemsToExport.First());
manager.WriteCaption(worksheet, SetCaptionStyle);
var row = 2;
foreach (var items in itemsToExport) {
manager.CurrentObject = items;
manager.WriteToXlsx(worksheet, row++, false);
}
xlPackage.Save();
}
return stream;
}
A controller action to return the file would look like this
public IActionResult Download(string guid) {
//...get list
var file = ExportToXlsx(list);
var contentType = "application/vnd.openxmlformats";
var fileName = "demo.xlsx";
return File(file, contentType, fileName); //returns a FileStreamResult
}
It was indicated in comments that the above is done in a support method.
Using the same approach
private readonly IServiceContext ctx;
//...
public void Download(string guid) {
//...get list
using(var fileStream = ExportToXlsx(list)) {
if (fileStream.CanSeek && fileStream.Position != 0) {
fileStream.Seek(0, SeekOrigin.Begin);
}
var contentType = "application/vnd.openxmlformats";
var fileName = "demo.xlsx";
var response = ctx.reqobj.HttpContext.Response;
response.Headers.Add("Content-Disposition", $"attachment; filename=\"{fileName}\"");
response.Headers.Add("Content-Length", fileStream.Length.ToString());
response.ContentType = contentType;
fileStream.CopyTo(response.Body);
}
}
the generated file is copied over to the body of the response.
As for postman, the tool is simply showing the content return in the response. It does not try to download the actual file as an attachment.

Export to CSV in mvc not work

I want to export a list to CSV file using MVC, Jquery. I want to write to a file to the response stream but doesn't do anything. No Download appear.
Below is my code in .cshtml
<button id="btnGenerateCSV">Generate CSV</button>
in .js
$('#btnGenerateCSV').click(function () {
$.post(root + "ClaimInternal/DownloadCsv");
});
In myController
private string GetCsvString(IList<Area> Area)
{
StringBuilder csv = new StringBuilder();
csv.AppendLine("AreaID,AliasName,Description,BankName");
foreach (Area area in Area)
{
csv.Append(area.AreaID + ",");
csv.Append(area.AliasName + ",");
csv.Append(area.Description + ",");
csv.Append(area.BankName + ",");
csv.AppendLine();
}
return csv.ToString();
}
public void DownloadCsv()
{
using (Database db = new Database(_ConnectionString))
{
AreaDAC dacArea = new AreaDAC(db);
List<Area> data = dacArea.Search("", "", "");
string facsCsv = GetCsvString(data);
// Return the file content with response body.
Response.ContentType = "text/csv";
Response.AddHeader("Content-Disposition", "attachment;filename=Area.csv");
Response.Write(facsCsv);
Response.End();
}
}
I try to make like this also
public FileContentResult DownloadCsv()
{
using (Database db = new Database(_ConnectionString))
{
AreaDAC dacArea = new AreaDAC(db);
List<Area> data = dacArea.Search("", "", "");
JsonResult result = new JsonResult();
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
result.Data = data;
string facsCsv = GetCsvString(data);
return File(new System.Text.UTF8Encoding().GetBytes(facsCsv), "text/csv", "Area.csv");
}
}
I make also like this
public void DownloadCsv()
{
using (Database db = new Database(_ConnectionString))
{
AreaDAC dacArea = new AreaDAC(db);
List<Area> data = dacArea.Search("", "", "");
string facsCsv = GetCsvString(data);
// Return the file content with response body.
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=Area.csv");
Response.Charset = "";
Response.ContentType = "application/text";
Response.Output.Write(facsCsv);
Response.Flush();
Response.End();
}
}
But still not work.. No download CSV appear.. While When I got it all working, no error.
Now I already got the answer. I change the script like this and it's work..
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "Area.csv",
Inline = true,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(new System.Text.UTF8Encoding().GetBytes(facsCsv), "text/csv");
It's work by adding new System.Net.Mime.ContentDisposition. But I'm still not understand why.
I was able to do using
window.location = "/urlPath?filename=" + filename;
and in my controller
filename = filename.ToString();
byte[] fileBytes = System.IO.File.ReadAllBytes(filename);
var response = new FileContentResult(fileBytes, "application/octet-stream");
response.FileDownloadName = "Filename.csv";
return response;

Issues with downloading PDF file from source

iv'e created a method to generate a pdf file from a form, it got saved to the correct path using itexsharp, but the problem is i can't download it.
this is my code :
private void FillForm(Dictionary<string, string> dic)
{
var pdfTemplate = HttpContext.Current.Server.MapPath("~/ress/GENE_15_04_2014.pdf"); //_pdfTemplet;
var newFile = _newFileName + "_" + Guid.NewGuid() + ".pdf";
_gNewFile = newFile.ToString();
var pdfReader = new PdfReader(System.IO.File.ReadAllBytes(pdfTemplate));
var pfileStream = new FileStream(string.Format(HttpContext.Current.Server.MapPath("~/ress/") + "{0}", newFile), FileMode.Create);
var pdfStamper = new PdfStamper(pdfReader, pfileStream);
var pdfFormFields = pdfStamper.AcroFields;
foreach (var entry in dic)
{
pdfFormFields.SetField(entry.Key, entry.Value);
}
pdfStamper.FormFlattening = true;
pdfStamper.JavaScript = "this.print(true);\r";
pdfStamper.Writer.CloseStream = false;
pdfReader.Close();
pdfStamper.Close();
UPContract.Update();
pfileStream.Close();
pdf.FilePath = string.Format("../Ress/{0}", Path.GetFileName(_gNewFile));
Response.Clear();
byte[] bytes = System.IO.File.ReadAllBytes(string.Format(HttpContext.Current.Server.MapPath("~/ress/") + "{0}", _gNewFile));
Response.ContentType = "application/pdf";
MemoryStream ms = new MemoryStream(bytes);
Response.AddHeader("content-disposition", "attachment;filename=" + "fiche abonnement_" + _gNewFile + ".pdf");
Response.Buffer = true;
ms.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}
If you want to pass a file you can skip the byte array and MemoryStream and just use Response.WriteFile(string)

File Stream not return after closing it in finally block C#

I have download files by returning as stream like below using WCF rest service.
Stream stream = null;
var directoryInformation = CommonServices.Utility.DirectoryHelper.GetTempFolderRootLocation();
string newFolderPath = directoryInformation + "\\Attachments\\" + Guid.NewGuid();
try
{
Directory.CreateDirectory(newFolderPath);
DataSet getDocumentContent = GetDocumentContent(engagementId, documentId);
var fileName = getDocumentContent.Tables[0].Rows[0]["Fullname"] as string;
var byteData= getDocumentContent.Tables[0].Rows[0]["FilestreamContent"] as byte[];
string fullPath = newFolderPath + "\\" + fileName;
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
if (byteData != null)
{
fileStream.Write(byteData,0,byteData.Length);
fileStream.Close();
}
if (WebOperationContext.Current != null)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream";
WebOperationContext.Current.OutgoingResponse.Headers.Add("content-disposition","inline; filename=" + fileName);
}
}
stream = File.OpenRead(fullPath);
return stream;
}
catch (Exception exception)
{
return null;
}
The above code works perfectly and can download the file in browser. But i have to delete the file after return the stream. So i have try to close and delete the file including the directory in finally block like below
finally
{
if (stream != null) stream.Close();
Directory.Delete(newFolderPath, true);
}
Full Method code
public Stream DownloadAttachment(string engagementId, string documentId)
{
Stream stream = null;
var directoryInformation = CommonServices.Utility.DirectoryHelper.GetTempFolderRootLocation();
string newFolderPath = directoryInformation + "\\Attachments\\" + Guid.NewGuid();
try
{
Directory.CreateDirectory(newFolderPath);
DataSet getDocumentContent = GetDocumentContent(engagementId, documentId);
var fileName = getDocumentContent.Tables[0].Rows[0]["Fullname"] as string;
var byteData= getDocumentContent.Tables[0].Rows[0]["FilestreamContent"] as byte[];
string fullPath = newFolderPath + "\\" + fileName;
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
if (byteData != null)
{
fileStream.Write(byteData,0,byteData.Length);
fileStream.Close();
}
if (WebOperationContext.Current != null)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream";
WebOperationContext.Current.OutgoingResponse.Headers.Add("content-disposition","inline; filename=" + fileName);
}
}
stream = File.OpenRead(fullPath);
return stream;
}
catch (Exception exception)
{
return null;
}
finally
{
if (stream != null) stream.Close();
Directory.Delete(newFolderPath, true);
}
}
After adding this code file is not downloaded in client.Is there any way to delete the file?Please help me to resolve this
You can delete the file in OperationContext.OperationCompleted as shown in http://devdump.wordpress.com/2008/12/07/disposing-return-values/
OperationContext clientContext = OperationContext.Current;
clientContext.OperationCompleted += new EventHandler(delegate(object sender, EventArgs args)
{
if (stream != null) stream.Close();
Directory.Delete(newFolderPath, true);
});
Change your method to this.
public void DownloadAttachment(string engagementId, string documentId, Action<Stream> processFile)
and instead of returning the stream call the processFile Action
processFile(stream);
This way you're not leaving the method in order to process the file. You will need to restructure the calling code in order to process the file though.

not able to export excel from gridview

this is my code:
protected void btnExcel_Click(object sender, ImageClickEventArgs e)
{
try
{
DataTable dtbl = (DataTable)ViewState["dtbl"];
string path = "E:\\shubby" + DateTime.Now.Day.ToString() + "_" + DateTime.Now.Month.ToString() + ".xls";
FileInfo fi = new FileInfo(path);
StringWriter sw = new StringWriter();
HtmlTextWriter htmltw = new HtmlTextWriter(sw);
DataGrid grdCrew = new DataGrid();
grdCrew.DataSource = dtbl;
grdCrew.DataBind();
grdCrew.RenderControl(htmltw);
string directory = path.Substring(0, path.LastIndexOf("\\"));// GetDirectory(Path);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
System.IO.StreamWriter vw = new System.IO.StreamWriter(path, true);
sw.ToString().Normalize();
vw.Write(sw.ToString());
vw.Flush();
vw.Close();
WriteAttachment(fi.Name, "application/vnd.ms-excel", sw.ToString());
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public static void WriteAttachment(string FileName, string FileType, string content)
{
HttpResponse Response = System.Web.HttpContext.Current.Response;
Response.ClearHeaders();
Response.AppendHeader("Content-Disposition", "attachment; filename=" + FileName);
Response.ContentType = FileType;
Response.Write(content);
Response.End();
}
I have seperate file for business logic and stored procedures, everything is working fine, its just the excel export that i am facing trouble with,
the error that i am getting is the exception that says "A required privilege is not held by the client"...
please help

Categories