I'm trying to send a 9MB .xls file as a response from web api controller method. The user will click a button on the page and this will trigger the download via the browser.
Here's what I've got so far but it doesn't work however it doesn't throw any exceptions either.
[AcceptVerbs("GET")]
public HttpResponseMessage ExportXls()
{
try
{
byte[] excelData = m_toolsService.ExportToExcelFile();
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new MemoryStream(excelData);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Data.xls"
};
return result;
}
catch (Exception ex)
{
m_logger.ErrorException("Exception exporting as excel file: ", ex);
return Request.CreateResponse(HttpStatusCode.InternalServerError);
}
}
Here is the coffeescript/javascript jquery ajax call from a button click in the interface.
$.ajax(
url: route
dataType: 'json'
type: 'GET'
success: successCallback
error: errorCallback
)
Now that I think about it perhaps the dataType is wrong and shouldn't be json...
I had to make a couple of small changes to get this to work
First: Change the method to a post
[AcceptVerbs("POST")]
Second: Change from using the jQuery ajax lib to use a hidden form, here's my service function for doing the hidden form and submitting it.
exportExcel: (successCallback) =>
if $('#hidden-excel-form').length < 1
$('<form>').attr(
method: 'POST',
id: 'hidden-excel-form',
action: 'api/tools/exportXls'
).appendTo('body');
$('#hidden-excel-form').bind("submit", successCallback)
$('#hidden-excel-form').submit()
Hopefully there's a better way to do this but for the time being it's working and downloading the excel file nicely.
Works also as a HTTP GET method, but don't use $ajax, instead use window.open(url);
C# code:
[HttpGet]
[Route("report/{scheduleId:int}")]
public HttpResponseMessage DownloadReport(int scheduleId)
{
var reportStream = GenerateExcelReport(scheduleId);
var result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(reportStream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Schedule Report.xlsx"
};
return result;
}
JS code:
downloadScheduleReport: function (scheduleId) {
var url = baseUrl + 'api/Tracker/report/' + scheduleId;
window.open(url);
}
I experienced the same problem. Problem solved with the following:
window.open(url)
It will store the excel file created in a folder in the system and once its sent to Browser, it will be deleted .
//path to store Excel file temporarily
string tempPathExcelFile = AppDomain.CurrentDomain.BaseDirectory + DateTime.Now.Hour + DateTime.Now.Minute +
DateTime.Now.Second + DateTime.Now.Millisecond +
"_temp";
try
{
//Get Excel using Microsoft.Office.Interop.Excel;
Excel.Workbook workbook = ExportDataSetToExcel();
workbook.SaveAs(tempPathExcelFile, workbook.FileFormat);
tempPathExcelFile = workbook.FullName;
workbook.Close();
byte[] fileBook = File.ReadAllBytes(tempPathExcelFile);
MemoryStream stream = new MemoryStream();
string excelBase64String = Convert.ToBase64String(fileBook);
StreamWriter excelWriter = new StreamWriter(stream);
excelWriter.Write(excelBase64String);
excelWriter.Flush();
stream.Position = 0;
HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
httpResponseMessage.Content = new StreamContent(stream);
httpResponseMessage.Content.Headers.Add("x-filename", "ExcelReport.xlsx");
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-excel");
httpResponseMessage.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = "ExcelReport.xlsx";
httpResponseMessage.StatusCode = HttpStatusCode.OK;
return httpResponseMessage;
}
catch (Exception ex)
{
_logger.ErrorException(errorMessage, ex);
return ReturnError(ErrorType.Error, errorMessage);
}
finally
{
if (File.Exists(tempPathExcelFile))
{
File.Delete(tempPathExcelFile);
}
}
//Javascript Code
$.ajax({
url: "/api/exportReport",
type: 'GET',
headers: {
Accept: "application/vnd.ms-excel; base64",
},
success: function (data) {
var uri = 'data:application/vnd.ms-excel;base64,' + data;
var link = document.createElement("a");
link.href = uri;
link.style = "visibility:hidden";
link.download = "ExcelReport.xlsx";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
error: function () {
console.log('error Occured while Downloading CSV file.');
},
});
In the end create an empty anchor tag at the end of your html file. <a></a>
This will return a file when you click a particular button
public FileResult ExportXls(){
//the byte stream is the file you want to return
return File(bytes, "application/msexcel")
}
来源:https://stackoverflow.com/questions/14831860/download-excel-file-from-page-via-webapi-call