内容处置不会导致另存为

发布于 2024-12-26 10:10:38 字数 1221 浏览 1 评论 0原文

我有以下代码:

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();

此操作是由以下 jquery 代码触发的:

   <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);}
                         });" />

我已通过 fiddler 确认标头具有预期值。我还可以使用 Web 视图查看 fiddler 中的数据。

另外,当我显示成功函数中的数据内容时,它具有我试图导出到 Excel 的表的原始 html。

预先感谢您的帮助。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谁把谁当真 2025-01-02 10:10:38

哦,不,你不能使用 AJAX 来下载文件。 AJAX 调用被执行,文件被传输到客户端,您的成功回调被执行并传递文件的内容,这就是您将被卡住的地方。出于明显的安全原因,您无法对这些数据做太多事情。您无法将其保存到客户端计算机。在此阶段您无法显示“另存为”的提示。

因此,删除您的 javascript AJAX 调用并使用正常的 GET 或 POST 请求调用您的控制器操作。

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.

挖个坑埋了你 2025-01-02 10:10:38

我建议不要将该代码直接放入 Action 方法中——这不是使用 MVC 的一种非常干净的方式,而且您当然无法从 AJAX 请求触发文件下载。

您可以从 FileResult 类派生一个新的操作结果(将其称为 ExcelResult),覆盖其 ExecuteResult 方法以强制将内容放入响应

单击按钮应该只需通过链接点击操作(导航到它)。服务器和浏览器的响应将共同作用,将文件强制发送给用户,而无需浏览到新页面。

示例:

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();
    }

}

您的操作很简单:

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

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 */);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文