【问题标题】:Execute javascript code at the end of event handler在事件处理程序结束时执行 javascript 代码
【发布时间】:2014-03-05 05:49:38
【问题描述】:

我正在使用 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 代码都是在所有代码隐藏执行后运行的,但在这种情况下,一旦文件发送到客户端,它就根本不会执行。

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

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

【问题讨论】:

  • 您没有在此处发送 HTML 页面。浏览器正在接收excel文档或将其提供给用户下载,因此没有页面。没有页面 - 没有要执行的 javascript。
  • @Andrei,我明白了,谢谢。

标签: c# javascript asp.net loading


【解决方案1】:

您只能在一个请求/响应周期中发送或传输 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;
            }
        }
    }
}

【讨论】:

  • 我可以给你举个例子,但我只能在星期一才能使用合适的计算机,IST :)
  • 太好了,谢谢!我将对此进行更多搜索,但请在星期一给出示例。
  • 嗨,如果用户在浏览器上禁用 cookie,您认为会发生什么?会有用吗?
  • 我想您的设计必须处理这种情况。看看这里的想法:stackoverflow.com/questions/531393/…
【解决方案2】:

看来您在这里有一些误解。您只有一个请求和来自服务器的一个响应。创建新线程只发生在服务器上,不会产生额外的响应。

当您发送 Excel 文件时,您正在使用:

HttpContext.Current.Response.Clear();

通过清除响应,您将丢失之前添加的 JavaScript。它永远不会到达客户端。

如果处理过程相当简单(总是只有几秒钟),我只需将加载动画设置为运行几秒钟然后停止,方法是在初始 onclick 事件上设置超时。它并不完美,但它会给用户一些即时反馈。

如果处理需要很长时间或非常多变的时间,那么动画就更重要了。您可以尝试在隐藏的&lt;iframe&gt; 中加载您的 Excel 文件,并附加一个 onload 事件以移除加载动画。

您需要创建一个单独的页面来处理生成 Excel 文件,而不是在服务器端 OnClick 处理程序中进行。但是,我似乎记得在旧 IE 版本上对 &lt;iframe&gt; 上的 onload 事件的支持可能参差不齐。

【讨论】:

  • 不好意思,这个和deostroll基本一样的答案,我没看到。
【解决方案3】:

当页面在浏览器中加载时,javascript 在客户端运行。您可能有一个隐藏的文本框,在事件结束时您可以在该文本框中输入一个值:

txtHidden.Text = "Hola Mundo"

您必须检查页面加载时的值:

<script type="text/javascript">
$(document).ready(function(){
  if($("#txtHidden").length > 0 && $("#txtHidden").val() != '')
  {
    alert($("#txtHidden").val());
  }
});
</script>

您可以将它放在网络用户控件中。 另一种解决方案:

<div class='button' id='btnGenerateDownload' onClick='GenerateDownload(this)'>
 Click here <div id='loadingImage' class='loadingImage'></div>
</div>

jQuery:

function GenerateDownload(caller)
{
   //add loading gif:
   var $loagingGIF = $(caller).children('#loadingImage').eq(0);
   $loagingGIF.addClass('loadingImage');
   var fileGeneratorUrl = 'ghFileGenerator.ashx';
   var downloadHandlerUrl = 'ghDownloadHandler.ashx';
   $.post({data: "File1"}, function(response){
     //remove gif
     $loagingGIF.removeClass('loadingImage');
     if(response != '') //file key
     {
       downloadHandlerUrl += '?key=' + response;
       var $link = $("<a />").attr('href', downloadHandlerUrl).html('download');
       $link.appendTo($(caller));
     }
   });
}

css:

.loadingImage{background: transparent url(images/loading.gif);}

.ashx:

 string filekey = context.Current.Request.Form("key");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多