c# - 在事件处理程序结束时执行 javascript 代码

标签 c# javascript asp.net loading

我正在使用 C# 在 ASP.NET 上构建 Web 应用程序。 在执行数据库查询时,单击按钮会显示加载图像。然后我动态创建一个 Excel 文件并将其发送给客户端,如下所示:

HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=" + filename + ".xlsx");
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Unicode;
HttpContext.Current.Response.BinaryWrite(p.GetAsByteArray());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End(); 

我得到对话框,加载图像保留在那里。

我试过在上面的代码之前调用一个 javascript 函数(使用 ClientScript.RegisterStartupScript 函数),但没有成功。据我所知,所有 javascript 代码都在所有代码隐藏执行后运行,但在这种情况下,一旦文件发送到客户端,它就根本不会执行。

我也试过创建一个单独的线程,并在那里删除加载图像。我打断点跟踪它,线程中的代码确实执行了,但图像仍然停留在那里。

有人知道如何处理吗?谢谢!

最佳答案

您只能在一个请求/响应周期内发送或传输 1 种 MIME 类型。 (我在这方面的知识值得商榷)。

也就是说,您可以围绕此设计一个 hack。在客户端上使用 iframe 来“下载文件”。您可以将其 src 指向执行相同操作的 ashx 文件。

您需要连接 iframe 的 onload 事件,以便您的网页知道下载已完成;这就是您可以执行逻辑的地方。

解决方案更新:

好吧,在四处挖掘之后,发现我的答案是半生不熟!

问题是 iframe 在下载内容后不会触发它们的 onload 事件。如果 src 指向的 url 实际导航到不同的页面,则 onload 事件将触发。我想这是设计使然。我今天才知道!

那么解决方法是什么?!

幸运的是,您可以将 cookie 传输到客户端。在客户端上,您的网页必须不断轮询此 cookie 的存在。因此,一旦您的网页能够检测到 cookie 的存在,就意味着浏览器已完成下载请求。这已在以下帖子中进行了非常详细的讨论:

http://geekswithblogs.net/GruffCode/archive/2010/10/28/detecting-the-file-download-dialog-in-the-browser.aspx

我将向您展示一些与处理程序文件(模拟下载)和客户端(使用 iframe 执行此工作)相关的代码。这几乎可以为您提供要点:

Webform1.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApp.FileDownload.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>iFrame Download</title>
    <script type="text/javascript" src="Scripts/jquery-2.1.0.min.js"></script>
    <script type="text/javascript" src="Scripts/jquery.cookie.js"></script>
    <script type="text/javascript">
        function foo() {
            console.log('foo');
            //execute post-download logic here
        }
        $(function () {            
            $('input').click(function () {
                //make sure we get rid of the 
                //cookie before download
                $.removeCookie('downloaded');

                var intrvl = setTimeout(function () { //this function polls for the cookie through which we track that the file has indeed been downloaded
                    console.log('timer');
                    var value = $.cookie('downloaded');
                    if (value == 'true') {
                        clearTimeout(intrvl);
                        foo();
                    }
                }, 1000);

                //this initiates the download
                $('iframe').attr({
                    'src': 'download.ashx?id=' + $('#tbxRandomNumber').val()
                });

            });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:TextBox ID="tbxRandomNumber" runat="server"></asp:TextBox>
        <input type="button" value="Download" />
        <iframe src="about:blank" style="display:none"></iframe>
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Next Random Number" />
    </div>
    </form>
</body>
</html>

我已经使用了 jquery cookies plugin帮助我处理 cookie。

下载.ashx:

using System;
using System.Web;

namespace WebApp.FileDownload
{
    /// <summary>
    /// Summary description for download
    /// </summary>
    public class download : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {            
            context.Response.ContentType = "text/plain";
            context.Response.SetCookie(new HttpCookie("downloaded","true")); //setting cookie in the response
            string id = context.Request.QueryString["id"] == null ? "NULL" : context.Request.QueryString["id"];
            string str = string.Format("Content with id {0} was generated at {1}", id, DateTime.Now.ToLongTimeString());

            context.Response.AddHeader("Content-Disposition", "attachment; filename=test.txt");
            context.Response.AddHeader("Content-Length", str.Length.ToString());
            context.Response.Write(str);
            context.Response.End();
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

关于c# - 在事件处理程序结束时执行 javascript 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21634151/

相关文章:

javascript - IE9 中的 "SCRIPT5039: Redeclaration of const property"

javascript - 如何在 asp.net 文档的末尾而不是在 ScriptManager 中注册 js 文件

c# - 从子用户控件访问父用户控件中的对象

c# - 分配 C# 事件处理程序的差异?

c# - 在颁发者名称与特定值匹配的集合中查找 X509 证书

c# - 没有可序列化属性的二进制序列化

.net - 使用 jQuery 的 ASP.NET Webforms?

c# - 如何制作表格中心的面板?

javascript - 拉斐尔改变方向动画

javascript - 如何使用 javascript 调用 ALM 中存在的 uft 脚本?