13

I would like to provide a file download operation by using the jQuery AJAX call with some params under MVC

Example

(javascript)
function DoDownload(startDate) {

  $.ajax({ 
     url:"controller/GetFile/",
     data: {startDate:startDate}
     ...
  });

}

C# Controller Code

 public void GetFile(string startDate) {

  var results = doQueryWith(startDate);

   // Create file based on results
   ....
   // How do I tell the server to make this a file download??
 }

I typically would just make my file download a link such as:

<a h r e f="mycontroller/getfile/1"/>Download</a>

but in the case above the date will be dynamic.

If I don't use ajax, what would be a preferred way to pass in the params to the MVC controller using javascript?

Example:

window.location  = "mycontroller/GetFile/" + $("#fromDate").val();

assuming the date is 12-25-2012

Would this produce

mycontroller/GetFile/12/25/2012

would MVC treat this as three params?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Arcadian
  • 4,312
  • 12
  • 64
  • 107
  • The answer to your question can be found at [this][1] link. [1]: http://stackoverflow.com/questions/5826649/returning-a-file-to-view-download-in-mvc/5830215#5830215 – Bhushan Firake Dec 30 '12 at 05:33
  • Unless you need a "hackable" URL, I am not sure you need to do it this way. Just pass the date as a parameter to a controller method and then use the suggested FileResult implementation. You may be making this harder than it needs to be? – Tim Hobbs Dec 30 '12 at 15:29

5 Answers5

12

What I ended up doing is calling my controller from my javascript like:

var url = "/mycontroller/GetFile?startDate=" + $("#mydate").val() + etc...

window.location = url;

mycontroller.cs

 public void GetFile(DateTime startDate) 
{

}

My original concern was with the date parameters. I didnt want to have to parse it.

Arcadian
  • 4,312
  • 12
  • 64
  • 107
  • One more comment, despite of the different dates in the world it's very accepted now everywhere to use ISO-8601 instead of any other format. Unfortunately MVC wraps dates in a weird way and it's not exactly the most popular one. I suggest you always to use ISO-8601 because you can change your controller in the future in an easier way. – Maximiliano Rios Dec 16 '14 at 12:32
  • This works perfectly for downloading a file where a jQuery Ajax call does not. Thank you for this terse yet elegant solution! – PhillipPDX Jun 05 '17 at 19:48
4

Using the ActionLink helper, you can pass multiple params to your controller:

HtmlHelper.ActionLink(
    string linkText, 
    string actionName, 
    string controllerName, 
    object routeValues, 
    object htmlAttributes
)

So in your case:

@Html.ActionLink("Download file", "GetFile", "MyController", new { startDate = "##" }, new { id="mydownloadlink" })

Using jQuery you can change the value of the startDate in the link with the content of your date picker or textbox.

$("#mydownloadlink").attr("href").replace("##", $("#yourdatetexbox").val);

Then, in your controller, just use one of the other answers here, about FileResult.

Hope this help you...

Romias
  • 13,783
  • 7
  • 56
  • 85
3

You can use the File method of controller class to return a file back to the browser.

The below sample returns a pdf file.

public ActionResult GetFile(int id)
{
  var fileInfo=repositary.GetFileDedetails(id);
  var byteArrayOFFile=fileInfo.FileContentAsByteArray();
  return File(byteArrayOFFile,"application/pdf","yourFriendlyName.pdf");
}

Assuming repositary.GetFileDedetails method returns the details of the file from the id.

You may also return the file from a physical location(a path) or a stream. Check all the overloads of the File method and use appropriate one.

This has nothing to do with ajax. this is normal GET request over a browser.

Shyju
  • 214,206
  • 104
  • 411
  • 497
1

Your controller action method should return a FileResult instead of void. And there is no need to do this via AJAX - in fact, you don't want to do this with AJAX. You'll need the browser involved so it knows to provide a download dialog for the user.

See these links:

Handling an ASP.NET MVC FileResult returned in an (jQuery) Ajax call

File download in Asp.Net MVC 2

I hope this helps.

Community
  • 1
  • 1
M.Ob
  • 1,785
  • 14
  • 27
0

This works for me. Make sure you return a File from your controller action with contentType as "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" and file name as e.g. "List.xlsx" which should be the same as in the AJAX success call. I have used ClosedXML NuGet package to generate the excel file.

public IActionResult GetFile(DateTime startDate)
    {
        var results = doQueryWith(startDate);
        DataTable dt = new DataTable("Grid");
        //populate dt here.
        //if you result is a data table you can assign it to dt
        dt = results;
        string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        string fileName = "List.xlsx";

        using (var workbook = new XLWorkbook())
        {
            workbook.Worksheets.Add(dt);

            using (var stream = new MemoryStream())
            {
                workbook.SaveAs(stream);
                workbook.SaveAs(stream);
                var content = stream.ToArray();
                return File(content, contentType, fileName);
            }
        }
    }

//.cshtml (JQuery AJAX call to the controller action)
$.ajax({
    url:"ControllerName/GetFile/",
    data: {startDate:startDate}     
    contentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    xhrFields: { responseType: 'blob' },
    success: function (data) {
        var a = document.createElement('a');
        var url = window.URL.createObjectURL(data);
        a.href = url;
        a.download = 'List.xlsx';
        a.click();
        window.URL.revokeObjectURL(url);
    }
});
Akbar
  • 71
  • 1
  • 3