如何让ASP.NET页知道何时可以从服务器下载文件 [英] How to let a ASP.NET page know when a file is ready for download from the server

查看:48
本文介绍了如何让ASP.NET页知道何时可以从服务器下载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在维护旧版VB.Net Webforms应用程序,添加一个部分后出现了一个奇怪的问题.

I'm maintaining a legacy VB.Net Webforms App and I've got a strange issue after adding one section.

aspx页面中的以下代码是在执行回发时显示giphy.gif的代码:

This is this code in the aspx page which shows the giphy.gif while doing a postback:

<style type="text/css">
    .modalWait
    {
        position: fixed;
        top: 0;
        left: 0;
        background-color: black;
        z-index: 99;
        opacity: 0.5;
        filter: alpha(opacity=80);
        -moz-opacity: 0.8;
        min-height: 100%;
        width: 100%;
    }
    .loading
    {
        font-family: Arial;
        font-size: 10pt;
        /*border: 5px solid #67CFF5;*/
        width: 100px;
        height: 100px;
        display: none;
        position: fixed;
        background-color: transparent;
        z-index: 999;
    }
</style>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
    function ShowProgress() {
        setTimeout(function () {
            var modal = $('<div />');
            modal.addClass("modalWait");
            $('body').append(modal);
            var loading = $(".loading");
            loading.show();
            var top = Math.max($(window).height() / 2 - loading[0].offsetHeight / 2, 0);
            var left = Math.max($(window).width() / 2 - loading[0].offsetWidth / 2, 0);
            loading.css({ top: top, left: left });
        }, 200);
    }
    $('form').live("submit", function () {
        ShowProgress();
    });
</script>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<form runat="server">
    <asp:ScriptManager runat="server"></asp:ScriptManager>

        <!-- Page Wrapper -->
        <div id="wrapper">

        <!-- More Code -->

        </div>
        <!-- End of Page Wrapper -->

        <div class="loading" align="center">
            <%--Loading. Please wait.<br /><br />--%>
            <img src="../img/giphy.gif" />
        </div>

</form>

它对于填充控件的所有查询都非常有效-.gif会在调用数据库时显示,然后消失.

And works perfectly for all the queries which populate the controls - the .gif appears while the database is called and then goes away.

但是后来我添加了一个函数,将datagrid读取到.csv文件中,然后下载它.除非我在后面的代码中添加此部分,否则它会完美运行:

But then I added a function to read the datagrid into a .csv and then download it. It works perfectly, except when I add this section in the code behind:

Dim bytes As Byte() = Encoding.ASCII.GetBytes(sb.ToString())

Response.Clear()
Response.ContentType = "text/csv"
Response.AddHeader("Content-Length", bytes.Length.ToString())
Response.AddHeader("Content-disposition", "attachment; filename=contacts.csv")
Response.Write(sb.ToString())
Response.Flush()
Response.End()

文件下载完美……但是giphy.gif仍然存在……即使回发已完成,它也不会消失.

The file downloads perfectly ... but the giphy.gif is still there ... it doesn't go away even though the postback has finished.

我做错了什么?

推荐答案

正如VDWWD解释的那样("UI从未更新,因为服务器一次只能发送一种类型的响应(文件或html页面)")真正的问题是您不知道何时完成文件下载(或更确切地说,当准备文件的服务器端代码完成执行时) ).

As VDWWD explained ("the UI is never updated because the server can only send one type of response at a time (a file or a html page)") your real problem is that you have no idea when the file download gets completed (or to be exact, when the server-side code, which prepares the file, has finished executing).

关于此

There are more than a handful of questions about this here on SO and amazingly almost always the answer is you cannot know!

嗯,还不完全!

您总是可以通过发回包含时间戳的唯一命名的cookie来让客户端知道.在客户端上,javascript代码会尝试检测cookie的存在,并在其出现时隐藏您所显示的任何加载图像(或文本或其他内容).

You can always let the client know by sending back a uniquely named cookie containing a time stamp. On the client, the javascript code tries to detect the cookie presence and when it does it hides any loading image (or text or whatever) you've shown.

因此,无需费力,这是代码(我仅使用loading css类使示例更简单,更小):

So, without further ado here's the code (I only used the loading css class to make the sample simpler and smaller):

<form id="form1" runat="server">        
    <div class="loading">
        Loading. Please wait.<br />
        <br />
    </div>
    <asp:HiddenField ID="windowid" runat="server" />        
    <asp:Button ID="Button1" runat="server" Text="Download" 
        OnClick="Button1_Click" 
        OnClientClick="ShowProgress();" />
</form>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>  

<script type="text/javascript">
    function ShowProgress() {           
        $(".loading").show();
        checkCookie();
    }

    function checkCookie() {
        var cookieVal = $.cookie($('#<%= windowid.ClientID %>').val());
        if (cookieVal == null || cookieVal === 'undefined') {
            setTimeout("checkCookie();", 1000);
        }
        else {
            $(".loading").hide();
        }
    }  
</script>

VB.NET的代码隐藏:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If Not IsPostBack Then
        ' the hidden value will be used to uniquely name the cookie and
        ' will be used both on the server and the client side to
        ' work with the cookie.
        windowid.Value = Guid.NewGuid().ToString()
    End If
End Sub

Protected Sub Button1_Click(sender As Object, e As EventArgs)
    ' for demo purposes only
    System.Threading.Thread.Sleep(4000)

    GetCsv()
End Sub

Protected Sub GetCsv()
    ' ... 

    Dim bytes As Byte() = Encoding.ASCII.GetBytes(sb.ToString())

    Response.Clear()
    Response.Cookies.Add(New HttpCookie(windowid.Value, DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss:ff")))
    Response.AddHeader("Content-Disposition", "attachment; filename=contacts.csv")
    Response.AddHeader("Content-Length", bytes.Length.ToString())
    Response.ContentType = "text/csv"
    Response.Write(sb.ToString())
    Response.Flush()
    Response.End()
End Sub

代码隐藏的C#:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        // the hidden value will be used to uniquely name the cookie and
        // will be used both on the server and the client side to
        // work with the cookie.
        windowid.Value = Guid.NewGuid().ToString();
    }
}


public void GetCsv()
{
    // ...    
    var bytes = Encoding.ASCII.GetBytes(sb.ToString());

    Response.Clear();
    Response.Cookies.Add(new HttpCookie(windowid.Value, DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss:ff")));
    Response.AddHeader("Content-Disposition", "attachment; filename=contacts.csv");
    Response.AddHeader("Content-Length", bytes.Length.ToString());
    Response.ContentType = "text/csv";
    Response.Write(sb.ToString());
    Response.Flush();
    Response.End();
}

protected void Button1_Click(object sender, EventArgs e)
{
    // for demo purposes only
    System.Threading.Thread.Sleep(2000);    

    GetCsv();
}

我希望这会有所帮助.如果可以,我建议我们编辑问题的标题(也许其中一些内容),以帮助其他人最终找到解决问题的可行解决方案,而该问题一直以来并未得到真正的回答.

I hope this helps. If it does I suggest we edit the title (and maybe some of the content) of the question so as to help others finally find a working solution to a problem that hasn't been really answered all this time.

这篇关于如何让ASP.NET页知道何时可以从服务器下载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆