强制 ASP.NET 回传

3
请查看以下点击事件...
Protected Sub btnDownloadEmpl_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDownloadEmpl.Click
    '下载员工数据表
    Dim emplTable As DataTable = SiteAccess.DownloadEmployee_H()
    '获取当前日期并格式化
    Dim d As String = Format(Date.Now, "d")
    '将日期转换为数组
    Dim ad() As String = d.Split("/")
    '拼接文件名
    Dim fd As String = ad(0) & ad(1)
    Dim fn As String = "E_" & fd & ".csv"
    '设置响应类型和文件名
    Response.ContentType = "text/csv"
    Response.AddHeader("Content-Disposition", "attachment; filename=" & fn)
    '创建CSV文件并输出到响应流
    CreateCSVFile(emplTable, Response.Output)
    '刷新响应流并结束响应
    Response.Flush()
    Response.End()
    '在页面上显示标签
    lblEmpl.Visible = True
End Sub
这段代码简单地将数据从datatable导出到csv文件。问题在于lblEmpl.Visible=true永远不会被执行,因为这段代码不会导致向服务器发送请求。即使我把代码行lblEmpl.Visible=true放在click事件的顶部,该行也能够正常执行,但页面仍然没有更新。我该如何解决这个问题?

你遇到了与此帖子相同的问题:http://stackoverflow.com/questions/2731971/problem-clearing-text-fields-on-vb-net-project-vs2008/2732657#2732657 - Chris Haas
4个回答

4

这行代码:

lblEmpl.Visible = True

这行代码永远不会被执行,因为:

Response.End()

抛出一个ThreadAbortException

我认为更加简洁的处理方式是创建一个简单的HttpHandler组件,并在弹出窗口中“打开”它。(弹出窗口实际上不应该打开。在大多数情况下,浏览器会意识到它实际上是一个下载,并且会禁止弹出新标签页/窗口。)

研究一下IHttpHandler接口。它们实际上非常容易实现。

这里有一个示例处理程序。对不起让你等了一会儿,我被叫去开会了:

public class CensusHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        string fileName = String.Format(
            CultureInfo.CurrentUICulture,
            "E_{0:00}{1:00}.csv",
            DateTime.Today.Month,
            DateTime.Today.Day
            );

        context.Response.ContentType = "text/csv";
        context.Response.AddHeader(
            "Content-Disposition", String.Format(null, "attachment; filename={0}", fileName)
            );

        //Dump the CSV content to context.Response

        context.Response.Flush();
    }

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

好的,请尝试添加一个JavaScript onclick事件来触发下载:

<asp:Button ID="Clickety" runat="server" Text="Click Me!" OnClick="Clickety_Click"
    OnClientClick="window.open('Handler.ashx', 'Download');" />

常规的 OnClick 事件将触发您的后台代码。而javascript onclick事件 (OnClientClick) 将通过 HttpHandler 启动下载。


如果我不在那里放置Response.End行,会有什么影响?有什么缺点吗? - Nick LaMarca
即使我将 Response.End 这一行注释掉,它仍然无法正常工作。 - Nick LaMarca
我正在搜索网络,不确定你的意思。我以前从未使用过HttpHandler。你能给我一个好的例子吗? - Nick LaMarca
我怎么使用这个东西?我一点头绪都没有,我一直在研究这些处理程序,但完全不知所措。 - Nick LaMarca
尝试这个。将“通用处理程序”项添加到您的Web应用程序中,并使用上面的代码。在我有“转储CSV…”注释的地方,放入context.Response.WriteLine("Hello World!");。现在在浏览器中打开.ashx模块并查看发生了什么。 - Toby
我看到它可以下载并将“Hello World”放入文件中,但是我该如何将其连接到我正在尝试的内容上呢?我有一个包含7个按钮(每个按钮对应一个下载)的aspx页面,页面上还有标签,标签旁边有标记为“download”的按钮,这些按钮不可见。当有人点击按钮时,我希望它下载文件(这个程序已经实现了),然后使标签可见,以便通知用户他们已经下载了此文件。我不确定如何将其连接起来,或者它如何帮助实现这一点? - Nick LaMarca

1

你应该选择弹出窗口,这样你仍然可以在原始页面上设置标签。从我所看到的,你可以这样做:

  1. 为弹出窗口创建一个单独的表单,将您的函数移动到新页面.cs的加载中,并向其发送一个查询字符串参数以导出其数据ID。

    Protected Sub onLoad()
        Dim recordID As Integer = Request.Querystring("dID")
        Dim emplTable As DataTable = Nothing 
        Select Case recordID 
          case 1: emplTable = SiteAccess.DownloadEmployee_H() 
          case 2: emplTable = SiteAccess.DownloadManagers() 
        End Select 
        Response.Clear()
        Response.ContentType = "text/csv"
        Response.AddHeader("Content-Disposition", "attachment; filename=" & fn)
        CreateCSVFile(emplTable, Response.Output)
        Response.Flush()
        Response.End() 
        lblEmpl.Visible = True
    End Sub
    
  2. 从按钮的onClientClick属性启动您的弹出窗口,或在postback上注册脚本。

    function fnPopUpCSV(expType)
    {        
    window.open('/popUpPage.aspx?dID=' + expType,'CSVwindow', 
    'width=300,height=200,menubar=yes,status=yes,
    location=yes,toolbar=yes,scrollbars=yes');
    }
    
    <asp:Button ID="btnGenEmplCSV" runat="server" Text="生成员工CSV"
    onClientClick="javascript:return fnPopUpCSV(1);" />
    
    <asp:Button ID="btnGenMgrCSV" runat="server" Text="生成经理CSV"
    onClientClick="javascript:return fnPopUpCSV(2);" />
    

谢谢你的帮助。你能给我更多细节吗?我不是专业人士。我需要这样做来添加缺失的部分吗?<code> Dim emplTable As DataTable =Nothing Select Case recordID case 1: emplTable = SiteAccess.DownloadEmployee_H() case 2: emplTable = SiteAccess.DownloadManagers() End Select </code> - Nick LaMarca
如果你只有两种获取数据的方法,那么我想你不需要变得太花哨。我只是编辑了示例,将代码放入了两个按钮中,并更改了js函数以通过参数传递。我还在服务器代码中添加了你的选择案例。希望这能帮到你。 - Tj Kellie
在您的情况下,我不确定 lblEmpl.Visible = True 是否可以被主页面看到。所以如果我正确理解了您的意思,这是我得到的结果。在主页面上,我有七个不同的 CSV 文件按钮(7 个按钮),例如 DownloadEmployee。我单击该按钮,在单击事件中运行 fnPopUp,它会转到另一个页面并下载,但标签位于主页面而不是弹出页面,因此它无法看到它。 - Nick LaMarca

1

你正在通过响应流发送CSV并结束它。因此,一旦你的所有代码运行完毕,页面本身就不再通过响应流发送,因此在浏览器中也不会更新。

为了实现你想要的效果,你需要创建第二个响应流。最简单的方法是通过一个新的浏览器窗口/弹出窗口来实现。然后你的CSV可以在弹出窗口中下载,而你的初始页面响应可以保留在初始浏览器中。


0

只需在 Page_Load 中使用此代码创建新页面

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) 
    Dim emplTable As DataTable = SiteAccess.DownloadEmployee_H()
    Dim d As String = Format(Date.Now, "d")
    Dim ad() As String = d.Split("/")
    Dim fd As String = ad(0) & ad(1)
    Dim fn As String = "E_" & fd & ".csv"
    Response.ContentType = "text/csv"
    Response.AddHeader("Content-Disposition", "attachment; filename=" & fn)
    CreateCSVFile(emplTable, Response.Output)
    Response.Flush()
    Response.End()
End Sub

然后在您的原始页面上,将lblEmpl设置为不可见,并注册以下脚本以打开一个新窗口并显示您的CSV文件。

var csvPageJS = string.Format("window.open ('{0}','mywindow');", ResolveUrl("~/MyCSVPage.aspx"));
  ClientScript.RegisterStartupScript(typeof(Page), "popup", csvPageJS, true);

我尝试过了,但它不起作用。它会下载数据,但无法刷新页面上的控件。 - Nick LaMarca
那段代码有点用。唯一的问题是它在显示标签之前更新页面,然后打开对话框。尽管我说要在脚本运行后显示标签。Dim csvPageJS As String = String.Format("window.open ('{0}','mywindow');", ResolveUrl("~/TESTLOAD.aspx")) ClientScript.RegisterStartupScript(GetType(Page), "popup", csvPageJS, True) lblRG.Visible = True - Nick LaMarca
尝试使用UpdatePanel,这样您就不会注意到页面加载,只需确保将ClientScript.RegisterStartupScript更改为ScriptManager.RegisterStartupScript以使其与异步回发配合工作。 - alejandrobog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接