I'm trying to download an excel file (generated on the fly) on a button click. The functionality works fine when the code is placed server side (Reports.aspx.cs) and there is a postback on the button click.
But, now, the front-end technology is Angular. So no postbacks. Tried to use the same download code in a handler and the download doesnt occur. No Save prompts, no errors. The breakpoint hits the handler.cs though.
Reports.aspx:
<button type="button" data-ng-click="DownloadExcelReport()">Download Report</button>
ReportsCtrl.js --controller
$scope.DownloadExcelReport = function () {
ReportsFactory.DownloadReport($scope.ReportId,$scope.SetId);
}
ReportsFactory.js --service
factory.DownloadReport = function (reportId, setId) {
return $http({
url: "http://localhost:62102/download.ashx?reportId=" + reportId + "&setId=" + setId,
method: "GET"
}).success(function (data, status) {
}).error(function (data, status) {
});
}
download.ashx.cs --handler
public void ProcessRequest(HttpContext context)
{
int reportId = Convert.ToInt32(context.Request.QueryString["reportId"]);
int setId = Convert.ToInt32(context.Request.QueryString["setId"]);
switch (reportId)
{
case 1:
DataTable dt = GetData(reportId, setId);
if (dt != null)
{
string FileName = "Responses";
ExportExcel obj = new ExportExcel();
obj.showGridLines = true;
obj.headerStyle = new Style(Color.SlateGray, Color.White, Color.SlateGray, ExcelBorderStyle.Thin);
MemoryStream ms = obj.GenerateDocument(dt);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + FileName + ".xlsx" + "\"");
HttpContext.Current.Response.BinaryWrite(ms.ToArray());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}
break;
}
}
EDIT:
I have later been taught that, when using Javascript to download, the approach is different.You create a form and then submit the form with parameters. I have added the working solution.
This might help someone.
ReportsFactory.js --service
factory.DownloadReport = function (reportId, setId) {
var form = document.createElement("form");
form.action = "http://localhost:62102/download.asmx/DownloadReport";
form.method = "POST";
form.target = "_self";
var input = document.createElement("input");
input.type = "text";
input.name = "params";
input.value = reportId + "," + setId;
form.appendChild(input);
form.style.display = 'none';
document.body.appendChild(form);
form.submit();
};
Using a asmx file now instead of handler.
download.asmx.cs
[WebMethod]
public void DownloadReport()
{
string[] Params = Convert.ToString(HttpContext.Current.Request.Form["params"]).Split(',');
string FileName = "Reports_";
int reportId = Convert.ToInt32(Params[0]);
int setId = Convert.ToInt32(Params[1]);
DataTable dt = GetData(reportId,setId);
ExportExcel obj = new ExportExcel();
MemoryStream ms = obj.GenerateDocument(dt);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + FileName + ".xlsx" + "\"");
HttpContext.Current.Response.BinaryWrite(ms.ToArray());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}
Related
I am using elasticsearch to query in index of PDFs on a asp.net mvc app. When I get the result I would like the user to be able to click the returned filename to download that file. Researching how to enable this functionality has returned plenty of results but none seem to work for me. I would simply like the user to be able to click on the filename and have the file download for them. I am using the below code.
To generate the dynamic table with search results
var row = $("<tr><th>" + "Search Results" + "</th><th>" + "File Name" + "</th>");
$("#myTable").append(row);
for (var i = 0; i < response.datasend.length; i++) {
var pos = response.datasend[i].Attachment.Content.indexOf(obj.searchterm);
var row = $("<tr><td>" + response.datasend[i].Attachment.Content.slice((pos - 100), (pos + 100)) + "</td><td><a href=# id=fileName>"
+ response.datasend[i].filename + "</a></td></tr>");
$("#myTable").append(row);
}
To detect the requested filename and call the function to start the download process
var table = document.getElementById("myTable");
table.addEventListener("click", function(e) {
if (e.target && e.target.id == "fileName")
{
var apiUrl = "/AllSearch/Download";
var obj = {};
obj.searchterm = e.target.innerHTML;
var params = e.target.innerHTML;
$.ajax({
contentType: 'application/json',
url: apiUrl,
dataType: "json",
data: {fileName: obj.searchterm},
success: function(data) {
alert("success");
},
error: function (xhr, err) {
alert("ready state: " + xhr.readyStat + " " + xhr.status);
}
});
}
});
To start download the file
public ActionResult Download(string fileName)
{
string filename = fileName;
string filePath = #"C:;at\to\file\Documents\" + fileName;
byte[] filedata = System.IO.File.ReadAllBytes(filePath);
string contentType = MimeMapping.GetMimeMapping(filePath);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = true,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(filedata, contentType);
}
The Download function is from Returning a file to View/Download in ASP.NET MVC but it returns an error when I run it. Not sure what I am missing here. Any help is appreciated
After calling API to get data, I need to generate the PDF file to PRINT using the default available.
Currently, Im able to get the data but then PDF not generated or downloaded.
AJAX codes to call controller to process request.
$(document).on('click', '#RePrint', function (event) {
var checkedVals = $('.ExportOrder:checkbox:checked').map(function () {
var orderId = this.value;
var status = document.getElementById(orderId).innerText;
if (status != "Received")
{
return this.value;
}
}).get();
if (checkedVals.length > 0) {
$.ajax({
url: '/Orders/RePrintLabel',
type: 'POST',
data: { ExportOrder: checkedVals },
dataType: "json",
async: true
});
}
});
Controller:
public ActionResult RePrintLabel(string[] ExportOrder)
{
var orders = ExtractOrders(ExportOrder, "Reprint");
if (orders.Count() > 0)
{
foreach (var item in orders)
{
var label = _orderMgr.RePrintLabel(item);
//Generate PDF For Label
if (label != null)
{
if (label.success)
{
byte[] byteContent = label.labels[0];
MemoryStream pdf = new MemoryStream(byteContent);
Response.Clear();
Response.ContentType = "application/pdf";
string pdfName = label.order_number;
Response.AddHeader("Content-Disposition", "attachment; filename=" + pdfName + ".pdf");
Response.ContentType = "application/pdf";
Response.Buffer = true;
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.BinaryWrite(byteContent);
Response.End();
Response.Close();
}
}
}
}
return RedirectToAction("Export");
}
The data is successfully returned and able to execute until this code Response.Close(); pdf was not downloaded or displayed to print.
Is there a way that I could automatically print the PDF file right after it is generated or the data is returned successfully using a default printer?
Thank you in advance for your help. Really appreciated.
I'm trying to download a file from server but this thing won't work. Been tring doing it for more than 2 weeks. Here is the code:
IN CSHTML PAGE:
<script type="text/x-jsrender" id="docView">
View
</script>
<script>
function docView(id) {
docId = id;
$.ajax({
type: "GET",
url: '#Url.Action("DownloadFile", "Profile")' + "?docid=" + docId,
dataType: "json",
success: function (result) {
},
});
</script>
IN MVC Controller:
[HttpGet]
public ActionResult DownloadFile(Guid? docid)
{
int i = 1;
string key = ConfigurationManager.AppSettings["PhysicalDocumentPath"];
JApplicantDocument value = new JApplicantDocument();
var response = new Response();
var fName = "";
var savefileName = "";
var fileSavePath = "";
var prevPath = "";
var nextPath = "";
try
{
IApplicantDataService applicantDataService = new ApplicantDataService();
response = applicantDataService.GetDocument(docid, value);
var fileName = value.ApplicantId + "_" + value.DocumentName;
fName = fileName;
savefileName = fileName;
fileSavePath = Path.Combine(key, fileName);
prevPath = fileSavePath;
nextPath = fileSavePath;
var tmp = fileName.Split('.');
var tmp1 = tmp[0];
while (System.IO.File.Exists(nextPath)) //to get the latest file
{
tmp = fileName.Split('.');
fileName = tmp1 + i.ToString();
fileName = fileName + "." + tmp[1];
savefileName = fileName;
nextPath = Path.Combine(key, savefileName);
if (System.IO.File.Exists(nextPath))
{
prevPath = nextPath;
}
i++;
tmp = prevPath.Split(new string[] { "Docs\\" }, StringSplitOptions.None);
fName = tmp[1];
response.Message = prevPath;
}
}
catch (Exception e)
{
Utils.Write(e);
}
return File(prevPath, value.Format);
}
I just want on click of View button to download the file as per this(http://www.c-sharpcorner.com/UploadFile/db2972/file-download-sample-in-mvc-day-40/). i cannot use location.href(...) directly in tag due to the fact that i'm using it in script jsrender which is being used in syncfusion grid controls. Hence I wont be able to get the docid at all.
I am using a webgrid and I have put a download button inside it to download a file from the grid.
But it throws an error: localhost sent an invalid response.
ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
[HttpGet]
public ActionResult DownloadStories()
{
string filename = "saddam.png";
string filepath = Server.MapPath("~/UploadedFiles/") + filename; //AppDomain.CurrentDomain.BaseDirectory + "/UploadedFiles/" + filename;
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
string contentType = MimeMapping.GetMimeMapping(filepath);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = true,
};
// Response.AppendHeader("Content-Disposition", cd.ToString());
Response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
return File(filedata, contentType, cd.FileName);
}
View:
WebGrid wgImages = new WebGrid(listData, rowsPerPage: 20);
#wgImages.GetHtml(tableStyle: "table table-condensed table-bordered table-striped table-responsive",
columns: wgImages.Columns(
wgImages.Column
(columnName: "Image", header:"Image"),
wgImages.Column
(columnName:"Story", header: "Story"),
wgImages.Column
(columnName:"Image", header:"Download", format: (testItem)=> Html.ActionLink("Download", "DownloadStories", "Stories")
))
);
}
I have tried the code which I have commented now and that doesn't work too.
Why not use simple HTML & JAVASCRIPT TO download the file by making an ajax call
1. Call this funcation by ajax post
[HttpPost]
public JsonResult DownloadStories(String someParamsIfany)
{
//do your thing
return Json(file,JsonRequestBehavior.AllowGet);
}
2. create an Img file with the data & download it on Html Side
$.ajax({
type: "POST",
url: '/Home/DownloadStories',
data: {someParamsIfany :someParamsIfany},
success: function (result) {
DownLoadTheFile(result);
}
});
3 now function DownLoadTheFile
function DownLoadTheFile(file){
var a = document.createElement('a');
a.href = file.filepath ;
a.download = file.filename;
a.click();
}
I want to export .frx report that designed by FastReport as an pdf or excel file on a c# web form application like code below:
public static bool ShowReport(string ReportFileName, DataTable ReportData, string DBObjectName, string ExportType, out string Message, params string[] AdditionalParams)
{
FastReport.Utils.Config.WebMode = true;
string ReportFile = HttpContext.Current.Server.MapPath(WPResources.ReportsRoot) + string.Format("{0}_{1}.frx", ReportFileName, ExportType.ToUpper());
FastReport.Report objReport = new FastReport.Report();
objReport.Load(ReportFile);
objReport.Dictionary.Connections.Clear();
System.Data.DataTable resultTable = new DataTable();
objReport.RegisterData(ReportData, DBObjectName);
objReport.GetDataSource(DBObjectName).Enabled = true;
int ParamsCount = AdditionalParams.Length;
if ((ParamsCount % 2) != 0)
ParamsCount--;
for (int i = 0; i < ParamsCount; i += 2)
{
var DynamicControl = (objReport.FindObject(AdditionalParams[i]) as FastReport.TextObject);
if (DynamicControl != null)
{
DynamicControl.Text = AdditionalParams[i + 1];
DynamicControl.Visible = !string.IsNullOrEmpty(AdditionalParams[i + 1]);
}
}
(objReport.FindObject("rptData") as FastReport.DataBand).DataSource = objReport.GetDataSource(DBObjectName);
string fileName = Path.GetFileNameWithoutExtension(ReportFile);
fileName += "_" + WPFarsiDate.Today.ToString().Replace("/", ".") + "_" +
DateTime.Now.Hour.ToString() + "." +
DateTime.Now.Minute.ToString();
if (ExportType == "Excel")
{
using (MemoryStream objMemoryStream = new MemoryStream())
{
objReport.Prepare(false);
FastReport.Export.OoXML.Excel2007Export objExcel2007Export = new FastReport.Export.OoXML.Excel2007Export();
objExcel2007Export.OpenAfterExport = false;
objExcel2007Export.Export(objReport, objMemoryStream);
byte[] buffer = objMemoryStream.ToArray();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("inline;filename={0}.xlsx", fileName));
HttpContext.Current.Response.BinaryWrite(buffer);
HttpContext.Current.Response.End();
}
}
else if (ExportType == "Pdf")
{
using (MemoryStream objMemoryStream = new MemoryStream())
{
objReport.Prepare(false);
FastReport.Export.Pdf.PDFExport objPDFExport = new FastReport.Export.Pdf.PDFExport();
objPDFExport.EmbeddingFonts = true;
objPDFExport.OpenAfterExport = false;
objPDFExport.Export(objReport, objMemoryStream);
byte[] buffer = objMemoryStream.ToArray();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}.pdf", fileName));
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.BinaryWrite(buffer);
HttpContext.Current.Response.End();
}
}
Message = string.Empty;
return true;
}
When I export it to excel, that is no any matter and it will be done successfuly. But when I export it to pdf, I get this error:
Showing a modal dialog box or form when the application is not running
in UserInteractive mode is not a valid operation. Specify the
ServiceNotification or DefaultDesktopOnly style to display a
notification from a service application.
It should be noted that mentioned error just occurs in the main server and the job can be done successfully in localhost.
It would be very helpful if someone could explain solution for this problem.
After much effort, I find solution for the problem. Fonts used in .frx files weren't the windows/fonts folder. So I copied the metioned fonts there and it worked properly.
Did you tried debug it? Which line throws this error?
Did you see any dialog windows in desktop version? Try to avoid it.
I use fast report in one of my ASP.Net Web Forms projects and I see this exception when I try to export PDF. I have this tag in .aspx file:
<fastreport:webreport id="remainedLeave" runat="server"
Width="100%" Height="100%"></fastreport:webreport>
Adding this property to fast report tag solved my problem:
PdfEmbeddingFonts="false"