content-disposition does not cause a save as

旧城冷巷雨未停 提交于 2020-01-03 17:11:15

问题


I have the following code:

Response.ClearContent();
Response.AddHeader( "Content-type", "application/vnd.ms-excel");
Response.AddHeader("content-disposition", "attachment;filename=test.xls");
Response.ContentType = "application/excel";
var swr = new StringWriter();
var tw = new HtmlTextWriter(swr);
grd.RenderControl(tw);
Response.Write(swr.ToString());
Response.Flush();
Response.End();
tw.Close();
swr.Close();

This action is triggered from the following bit of jquery code:

   <img src="../../../../Content/images/Excel-icon.png" 
      onclick = "alert ($('#Filter').serialize());
                    $.ajax({
                         type: 'POST',
                         url: '<%=Url.Action( "Excel") %>',
                         data: $('#Filter').serialize(),
                         success : function (data, textStatus, jqXHR) 
                              { alert (data);},
                         error: function (jqXHR, textStatus, errorThrown)
                              { alert (textStatus + ' ' + errorThrown);}
                         });" />

I have confirmed with fiddler that the headers have the expected values. I can also see the data in fiddler using the Web View.

Also, when I show the contents of data from the success function, it has the raw html for the table that I am trying to export to excel.

Thanks in advance for your help.


回答1:


Oh, no, you cannot use AJAX to download files. The AJAX call is executed, the file is streamed to the client, your success callback is executed and passed the contents of the file that's where you will get stuck. For obvious security reasons you cannot do much with this data. You cannot save it to the client computer. You cannot show a prompt to Save As at this stage.

So remove your javascript AJAX call and invoke your controller action using a normal GET or POST request.




回答2:


I would suggest not putting that code directly in an Action method -- that's not a very clean way to use MVC, and you certainly can't trigger a file download from an AJAX request.

You could derive a new action result -- call it ExcelResult -- from the FileResult class, an override its ExecuteResult method to force the content into the Response.

The button click should simply hit the action through a link (navigate to it). The response from the server and the browser will work together to force the file at a user without browsing to a new page.

Example:

public class ExcelResult : FileResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        string file;

        using (var swr = new StringWriter())
        {
            using (var tw = new HtmlTextWriter(swr))
            {
                // Not sure where your grd object comes from
                grd.RenderControl(tw);
                file = swr.ToString();
            }
        }

        var response = context.HttpContext.Response;

        response.Buffer = true;
        response.Clear();
        response.ClearHeaders();
        response.ContentType = "application/excel";
        response.CacheControl = "public";
        response.AddHeader("Pragma", "Public");
        response.AddHeader("Expires", "0");
        response.AddHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
        response.AddHeader("Content-Description", "describe your file");
        response.AddHeader("Content-Disposition","attachment; filename=excel.xls");
        response.Write(file);
        response.Flush();
        response.End();
    }

}

And your Action is simply:

public ExcelResult Excel()
{
    return new ExcelResult(/* whatever you need to pass */);
}


来源:https://stackoverflow.com/questions/8824630/content-disposition-does-not-cause-a-save-as

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!