2

In my ASP.NET MVC project, I generated a excel file using ClosedXML.

It works well in non-ajax call. Here is my controller action method

 // Prepare the response
 Response.Clear();
 Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
 Response.AddHeader("content-disposition", "attachment;filename=\"" + reportHeader + ".xlsx\"");

 // Flush the workbook to the Response.OutputStream
 using (MemoryStream memoryStream = new MemoryStream())
 {
     MyWorkBook.SaveAs(memoryStream);
     memoryStream.WriteTo(Response.OutputStream);
     memoryStream.Close();
 }
 Response.End();

Now I am trying to do it via an ajax request. But the file is not sent from mvc controller.

$.ajax({
                url: url,
                type: "POST",
                data: fd,
                processData: false,  
                contentType: false,  
                beforeSend: function () {
                },
                success: function (response) {

                },
                error: function (request, status, error) {
                },
                complete: function () {
                }
            });

How can i accomplish it? Thank you in advance.

s.k.paul
  • 7,099
  • 28
  • 93
  • 168

2 Answers2

7

Why not? ramiramilu was right about using window.location and iframe. I did the same thing but for ASP.NET MVC3.

I would suggest to use controller which returns FileContentResult

FYI about FileContentResult MSDN

And finally how I did it (Controller):

    [HttpPost]
    public HttpStatusCodeResult CreateExcel()
    {
        XLWorkbook wb = new XLWorkbook(XLEventTracking.Disabled); //create Excel

        //Generate information for excel file
        // ...

        if (wb != null)
        {
            Session["ExcelResult"] = wb;
            return new HttpStatusCodeResult(HttpStatusCode.OK);
        }

        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

    }

    [HttpGet]
    public FileContentResult ExcelResult(string reportHeader) //it's your data passed to controller
    {

        byte[] fileBytes = GetExcel((XLWorkbook)Session["ExcelResult"]);
        return File(fileBytes, MediaTypeNames.Application.Octet, reportHeader + ".xlsx");
    }

In model (you can remove static if you wish, and call it with instance)

public static byte[] GetExcel(XLWorkbook wb)
{
    using (var ms = new MemoryStream())
    {
        wb.SaveAs(ms);
        return ms.ToArray();
    }
}

AJAX:

$.ajax({
            url: "@Url.Action("CreateExcel")",
            async: true,
            type: "POST",
            traditional: true,
            cache: false,
            statusCode: {
                400: function () {
                    alert("Sorry! We cannot process you request");
                },
                200: function () {
                    $("#fileHolder")
                    .attr('src', 
                    '@Url.Action("ExcelResult")?reportHeader=' + 
                    reportHeader);
                }
            }
        });

BTW, I removed all exception handlers to simplify the code, but I assume You can do it yourself.

SouXin
  • 1,565
  • 11
  • 17
3

You cannot DIRECTLY download a file using AJAX, but you can download a file using window.location in conjunction with AJAX to make the file downloaded. What I mean is that if you use AJAX GET/POST all the file content will be in memory of the browser but cannot be saved to disk (because of JavaScript limitations).

Instead you can use window.location to point to a URL which in turn will fetch the file and prompt the save/open prompt. Or else you can use a hidden iFrame and set the src attribute of iFrame with the URL from which will download the file.

ramiramilu
  • 17,044
  • 6
  • 49
  • 66
  • Read comment on OP from @king.code. AJAX requests are possible and he references an example. This solved the problem for me and yes, it is possible to download a file with AJAX if you find the need to do so. – jaredbaszler May 07 '15 at 22:01
  • @jaredbaszler, if you look at the king.code post, even they used window.location. Can you clearly explain the reason behind down vote? – ramiramilu May 08 '15 at 04:13
  • Because you clearly state "you cannot download a file using AJAX" as your first sentence above. Which as you later state in your own post is not true. At first glance I was going to look for another alternative because of the way you presented your argument. Thankfully I read the response from @king.code above and found what I was looking for. Technically you are right about not downloading via AJAX but I wanted to utilize other features of AJAX with using window.location. The way you present your argument made me think that wasn't possible. – jaredbaszler May 08 '15 at 14:15
  • 1
    Agreed with your point, in that case a EDIT would make the essence of answer more appropriate, than projecting the entire answer as wrong one. – ramiramilu May 08 '15 at 14:35