Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excel file not being downloaded when function is called via ajax method

Situation

I am working on an application where I can have a grid with X items, and each item has a print button. Clicking this print button allows me to call an ajax function which passes the ID of the grid item to a controller. I retrieve the relevant data based on that ID and then download it in an excel file. (The retrieving of the specific item is not yet done)

What I have so far

So far, I have the basic code that downloads an excel file, along with my grid .

Problem

The problem I am facing is, if I click the "Print" button...nothing happens, even with a breakpoint in my exporttoexcel functions shows me that the function is entered and I can step thru it and despite no errors, nothing occurs. However, I added random button that called the same function and when i clicked that button, the excel file was downloaded. As a result, I believe the issue has something to do with aJax.

Code

<input type="button" value="Test" onclick="location.href='@Url.Action("ExportToExcel", "Profile")'" />

This is the code which downloads the file. It was a simple button I added.

function ExportToExcel(id) {
    $.ajax({
        type: "POST",
        url: "@Url.Action("ExportToExcel", "Profile")",
        data: { "id": id },
        dataType: "json"

    });
}

This is the function that I want to work, but it does not work and I cannot see what i've got wrong.

Export to Excel Code

public void ExportToExcelx()
{
    var products = new System.Data.DataTable("teste");
    products.Columns.Add("col1", typeof(int));
    products.Columns.Add("col2", typeof(string));

    products.Rows.Add(1, "product 1");
    products.Rows.Add(2, "product 2");
    products.Rows.Add(3, "product 3");
    products.Rows.Add(4, "product 4");
    products.Rows.Add(5, "product 5");
    products.Rows.Add(6, "product 6");
    products.Rows.Add(7, "product 7");


    var grid = new GridView();
    grid.DataSource = products;
    grid.DataBind();

    Response.ClearContent();
    Response.Buffer = true;
    Response.AddHeader("content-disposition", "attachment; filename=MyExcelFile.xls");
    Response.ContentType = "application/ms-excel";

    Response.Charset = "";
    StringWriter sw = new StringWriter();
    HtmlTextWriter htw = new HtmlTextWriter(sw);

    grid.RenderControl(htw);

    //Response.Output.Write(sw.ToString());
    //Response.Flush();
    //Response.End();
    // =============


    //Open a memory stream that you can use to write back to the response
    byte[] byteArray = Encoding.ASCII.GetBytes(sw.ToString());
    MemoryStream s = new MemoryStream(byteArray);
    StreamReader sr = new StreamReader(s, Encoding.ASCII);

    //Write the stream back to the response
    Response.Write(sr.ReadToEnd());
    Response.End();



    //  return View("MyView");
}

Theory

I believe the error is somehow tied in to aJax, I am also creating the button in the controller like this. "<button type='button' class='btn btn-warning' onclick='ExportToExcel(" + c.id + ");'>Print</button>",

Since location.href='@Url.Action works, I was wondering if attempting to redo my dynamic button would solve my issue.

Appreciate any insight that could be offered.

like image 427
Niana Avatar asked Feb 13 '20 03:02

Niana


People also ask

How can I download Excel file in Ajax?

Downloading Excel File using AJAX in jQueryInside the DownloadFile JavaScript function, the URL of the File is passed as parameter to the jQuery AJAX function. Inside the jQuery AJAX function, using the XmlHttpRequest (XHR) call, the PDF file is downloaded as Byte Array (Binary Data).

Can we download file using Ajax?

We cannot download the file through Ajax, must use XMLHttpRequest.


2 Answers

Yes you are right you have problem with ajax, Basically you have to call the controller action again from you ajax call when your first ajax call return success. Add below code snippet to your ajax call.

success: function () {

    window.location = '@Url.Action("ExportExcel", "Profile")?id='+id;
}

And you have to change your controller method to return the file, as below

public FileResult ExportToExcelx()
{
	...............
	
	byte[] byteArray = Encoding.ASCII.GetBytes(sw.ToString());
	return File(byteArray, System.Net.Mime.MediaTypeNames.Application.Octet, "FileName.xlsx");                       
}
like image 115
Abhishek Avatar answered Oct 29 '22 22:10

Abhishek


I've had a similar problem here, and it did solve with a dynamic button as well. I just had to include a responseType:'blob' in my request. And get the response to the button:

var link = document.createElement('a');
link.href = window.URL.createObjectURL(response.data);
link.download='filename.xlsx';

document.body.appendChild(link);
link.click();
document.body.removeChild(link);

And my Controller writes to a output stream and produces a "application/xls"

response.setContentType("application/xls");
response.setHeader("Content-disposition", "attachment;");
response.getOutputStream().write(content);
like image 42
Thiago Avatar answered Oct 29 '22 20:10

Thiago