You cannot directly return the file to be downloaded via an AJAX call, so an alternative approach is to use an AJAX call to send related data to your server. You can then use the server side code to create the Excel file (I would recommend using EPPlus or NPOI for this, although it seems like you have this part of the job).
UPDATE September 2016
My original answer (below) was over 3 years old, so I decided to upgrade since I no longer create files on the server when uploading files via AJAX, however I left the original answer, as this may be useful, it still depends on your specific requirements.
The usual script in my MVC applications reports via a web page with some user report settings configured (Date Ranges, Filters, etc.). When the user specified the parameters that they send to the server, a report is created (for example, an Excel file as output), and then I save the resulting file as a byte array in a TempData bucket with a unique link. This link is passed as a Json result for my AJAX function, which then redirects to a separate controller action to retrieve data from TempData and load the end users into the browser.
To give this in more detail, if you have an MVC View that has a form associated with the Model class, call Model ReportVM .
Firstly, to get a hosted model, a controller action is required, an example would be:
public ActionResult PostReportPartial(ReportVM model){
An AJAX call that submits my MVC form to the above controller and receives a response is as follows:
$ajax({ cache: false, url: '/Report/PostReportPartial', data: _form.serialize(), success: function (data){ var response = JSON.parse(data); window.location = '/Report/Download?fileGuid=' + response.FileGuid + '&filename=' + response.FileName; } })
Controller action to handle file upload:
[HttpGet] public virtual ActionResult Download(string fileGuid, string fileName) { if(TempData[fileGuid] != null){ byte[] data = TempData[fileGuid] as byte[]; return File(data, "application/vnd.ms-excel", fileName); } else{
Another change that can be easily done if necessary is to pass the MIME type of the file as the third parameter, so that one controller action can correctly serve different output file formats.
This eliminates the need for any physical files that have been created and stored on the server, so no housekeeping routines are required, and once again this becomes clear to the end user.
Note. The advantage of using TempData rather than Session is that after reading TempData data is cleared, so it will be more efficient in terms of memory usage if you have a large volume of file requests. See Best Practices for TempData .
ORIGINAL RESPONSE
You cannot directly return the file to be downloaded via an AJAX call, so an alternative approach is to use an AJAX call to send related data to your server. Then you can use the server side code to create the Excel file (I would recommend using EPPlus or NPOI for this, although it sounds like you have this part of the job).
Once the file was created on the server, return the file path (or just the file name) as the return value for your AJAX call, and then set the JavaScript URL window.location for this, which will force the browser to download the file.
From the point of view of end users, the file upload operation is seamless, as they never leave the page on which the request appears.
Below is a simple, contrived example of calling ajax to achieve this:
$.ajax({ type: 'POST', url: '/Reports/ExportMyData', data: '{ "dataprop1": "test", "dataprop2" : "test2" }', contentType: 'application/json; charset=utf-8', dataType: 'json', success: function (returnValue) { window.location = '/Reports/Download?file=' + returnValue; } });
- url is the Controller / Action method in which your code will create an Excel file.
- data strong> contains json data to be extracted from the form.
- returnValue will be the file name of your newly created Excel file.
- The window.location command redirects to the Controller / Action method, which actually returns your file to load.
Example controller method for the Download action:
[HttpGet] public virtual ActionResult Download(string file) { string fullPath = Path.Combine(Server.MapPath("~/MyFiles"), file); return File(fullPath, "application/vnd.ms-excel", file); }