How to pass authorization header for exporting request
To pass an authorization header when you export a report from the Bold Reports® JavaScript Report Viewer, handle the exportItemClick event and send the export request with your own Ajax call. By default, the Report Viewer and Report Designer do not have an option to pass the authorization header for the export request. For the reason, see How to resolve the image rendering and exporting issue with ASP.NET Core Authentication middleware.
You can add customized export functionality with authorization headers by using the exportItemClick event. The event is invoked when you export reports from the Report Viewer and the Report Designer preview. Follow these steps:
-
Set the “exportItemClick” on Bold Reports® Report Viewer initialization as shown in the following code sample.
$(function () { $("#viewer").boldReportViewer({ reportServiceUrl: "/api/ReportViewer", reportPath: 'sales-report.rdl', exportItemClick: onExportItemClick }); }); -
Implement the function and replace the following code samples to send export type to server side.
function onExportItemClick(args) { var exportType; var exportTypeFormat; if (args.value != null) { if (args.value == 'PDF') { exportType = 'PDF'; exportTypeFormat = 'PDF'; } else if (args.value == 'Word') { exportType = 'Word_' + args.model.exportSettings.wordFormat; exportTypeFormat = 'Word'; } else if (args.value == 'Excel') { exportType = 'Excel_' + args.model.exportSettings.excelFormat; exportTypeFormat = 'Excel'; } else if (args.value == 'CSV') { exportType = 'CSV'; exportTypeFormat = 'CSV'; } else { var text = $(args.target.textContent); exportTypeFormat = $(args.target).text(); } } if (args.value != null) { var _this = this; args.cancel = true; var proxy = $('#viewer').data('boldReportViewer'); var requrl = '/api/ReportViewer/ExportReport'; var _json = { exportType: exportType, reportViewerToken: _this['_reportViewerToken'] }; $.ajax({ contentType: "application/json; charset=utf-8", dataType: "json", type: "POST", url: requrl, data: JSON.stringify(_json), crossDomain: true, success: (data) => { if (data) { //Implement function to start the export } }, error: (data) => { alert("Ajax failure"); } }) } } -
Implement the function
ExportReportand replace the following code samples to get the report in the specified export type.public Dictionary<string, object> ExportReport([FromBody] Dictionary<string, object> jsonResult) { string types = null; string fileName = null; Guid fileId = Guid.NewGuid(); if (jsonResult.ContainsKey("exportType")) { type = null; types = type = jsonResult.Single(jr => jr.Key == "exportType").Value.ToString(); } token = jsonResult["reportViewerToken"].ToString(); if (types.Contains("PDF")) { fileName = "Name" + fileId.ToString() + ".pdf"; } else if (types.Contains("Word")) { fileName = "Name" + fileId.ToString() + ".doc"; } else if (types.Contains("Excel")) { fileName = "Name" + fileId.ToString() + ".xls"; } else if (types.Contains("CSV")) { fileName = "Name" + fileId.ToString() + ".csv"; } string _token = jsonResult["reportViewerToken"].ToString(); string type1 = jsonResult["exportType"].ToString(); var stream = ReportHelper.GetReport(_token, type1); var reportLocation = AppDomain.CurrentDomain.BaseDirectory; using (var fileStream = System.IO.File.Create(reportLocation + @"App_Data\\" + fileName)) { stream.Seek(0, SeekOrigin.Begin); stream.CopyTo(fileStream); } Dictionary<string, object> jsonData = new Dictionary<string, object>(); filename = null; filename = fileName; jsonData.Add("fileName", fileName); return jsonData; } -
After the Ajax request completes successfully, the report data is returned from the server side. Implement the function
exportReportat client side and replace the following code samples to pass the custom authentication in headers along with file data using blob.function exportItemClick() { ... ... $.ajax({ contentType: "application/json; charset=utf-8", dataType: "json", type: "POST", url: requrl, data: JSON.stringify(_json), crossDomain: true, success: (data) => { if (data) { //Implement function to start the export exportReport(data); } }, error: (data) => { alert("Ajax failure"); } }) } function exportReport(jsonData) { let url = `/api/ReportViewer/ExportStart`; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'authorization': 'authenticationtoken' }, responseType: 'json', body: JSON.stringify(jsonData) }).then(function (resp) { return resp.blob(); }).then(function (data) { var filename = null; Object.keys(jsonData).forEach(function (fileName) { filename = jsonData[fileName]; //Invoke the download file at client side }); }); } -
Implement the function
ExportReportat server side and replace the following code samples to start the export of the report with the file data.[HttpPost] public object ExportReport([FromBody] Dictionary<string, object> jsonResult) { string fileId = null; if (jsonResult.ContainsKey("fileName")) { fileId = jsonResult["fileName"].ToString(); } System.Net.Http.HttpResponseMessage response = new System.Net.Http.HttpResponseMessage(); try { string path = HttpContext.Current.Server.MapPath("~/App_Data/"); var stream = File.Open(path + fileId, FileMode.Open); stream.Position = 0; System.Web.HttpResponse httpResponse = System.Web.HttpContext.Current.Response; httpResponse.ClearContent(); httpResponse.Expires = 0; httpResponse.Buffer = true; httpResponse.AddHeader("Content-Disposition", "attachment;filename=\"" + fileId + "\""); httpResponse.AddHeader("Content-Type", "Application/" + type); httpResponse.Clear(); byte[] buffer = new byte[stream.Length + 1]; int bytesRead; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) { httpResponse.OutputStream.Write(buffer, 0, bytesRead); } response.StatusCode = System.Net.HttpStatusCode.OK; } catch (Exception ex) { response.StatusCode = System.Net.HttpStatusCode.NotFound; } return response; } -
Download the report on the client side as shown in the following code sample.
function exportReport(jsonData) { let url = `/api/ReportViewer/ExportStart`; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'authorization': 'authenticationtoken' }, responseType: 'json', body: JSON.stringify(jsonData) }).then(function (resp) { return resp.blob(); }).then(function (data) { var filename = null; Object.keys(jsonData).forEach(function (fileName) { filename = jsonData[fileName]; //Invoke the downloaf file at client side downloadFile(data, filename); }); }); } function downloadFile(fileData, filename) { // Create an object URL for the blob object const url = URL.createObjectURL(fileData); const a = document.createElement('a'); a.href = url; a.download = filename || 'download'; const clickHandler = () => { setTimeout(() => { URL.revokeObjectURL(url); this.removeEventListener('click', clickHandler); }, 150); }; a.addEventListener('click', clickHandler, false); a.click(); return a; }
See also
How to resolve the image rendering and exporting issue with ASP.NET Core Authentication middleware