nel codice di sotto ci potrebbero essere errori, dato che non ho collaudato bene.
Il problema è questo:

un pulsante client fa la richiesta al server per ottenere un file (ad esempio un file zip che richiede abbastanza tempo)

deve comparire un messaggio di attesa

a ricezione avvenuta si deve aprire la finestra salva/apri file

adesso deve scomparire il messaggio di attesa


Per ottenere questo, io procedo così:
al click del pulsante:
mostro messaggio attesa
faccio la richiesta post al server con target iframe nascosto
lancio una richiesta ajax temporizzata per scoprire se la richiesta al server è terminata
(nota: la apertura finestra salva/apri, non scatena nessun evento, perciò bisogna arrangiarsi)

pagina
codice:
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="download_mp3.aspx.vb" Inherits="CorsoApogeo_download_download_mp3" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>download mp3</title>
    <link href="../../stili/Styles.css" rel="stylesheet" type="text/css" />

    <script type="text/javascript" src="../../js/libreria.comp.js"></script>
    
<script language="javascript" type="text/javascript">
// <!CDATA[

//Dowload stringa RTF maniera indiretta con iframe nascosto (non dà problemi con IE6)
function Button4_onclick() 
{
    window.setTimeout(function()
            {
                disabilita_pagina(25);
                $('div_attendere').style.display = '';
                var wh = ClientSize();
                var w = wh.width;
                var h = wh.height;
                $("div_attendere").style.top = Math.round((h -50)/2) + "px";
                $("div_attendere").style.left = Math.round((w -250)/2) + "px";
            }, 1);
    
    download();
    chiedi_informazioni_download()
    
}

function chiedi_informazioni_download()
{
    ajax("?download=2", onload);
    function onload()
    {
        var t = this.request.responseText;
        var j = eval("(" + t + ")");
        if(j.download)
        {
            
            window.setTimeout(function()
				{
                    abilita_pagina();
                    $('div_attendere').style.display = 'none';
				}, 500);
            
                        
        }
        else window.setTimeout("chiedi_informazioni_download()", 500);
        
    }

}



/*---------------------------------------------------------------------------------------------
NOTA:   aprire la pagina in un iframe nascosto per recuperare il file kml è necessario per iE6
        Con IE7 non è necessario
---------------------------------------------------------------------------------------------*/
function download()
{
    //il codice di sotto commentato funziona perfettamente
    //window.open("titoli_di_cava_dati_atlanti.aspx?c_id_pratica=" + $("c_id_pratica").value + "&crea_kml=1" + "&c_denominazione=" + encodeURIComponent($("c_denominazione").value), "iframe1");
    submitData(window.location.pathname, 
        {
            download:'1', cb_errore:($("cb_errore").checked)?"on":""
        }, 
        "iframe1");
    
}


// ]]>
</script>

</head>
<body>
    <h3>Download mp3</h3>
    <form id="form1" runat="server">
        <label for="cb_errore">Simula errore</label><input type="checkbox" id="cb_errore" name="cb_errore" value="on" />
        <input id="Button4" type="button" value="Dowload mp3"  onclick="return Button4_onclick()" />




        <iframe id="iframe1" name="iframe1" style="display:none;" src=""></iframe>
        
        <div id="div_attendere" style="position:absolute; z-index:99999; left:100px;top:100px; width:250px; height:50px; background-color:White; border:10px red solid; padding:10px; text-align:center; display:none" >
            Prego attendere: operazione in corso...

            [img]../../immagini/pleasewait.gif[/img]
        </div>

    </form>
</body>
</html>
codice
codice:
Option Strict On

Partial Class CorsoApogeo_download_download_mp3
    Inherits System.Web.UI.Page

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Inserire qui il codice utente necessario per inizializzare la pagina

        If RequestParams("download") = "1" Then
            'questa chiamata fa partire il download sicuro
            'alla fine valorizzo la variabile session download a true
            Try

                'simulo un impegno di 3 secondi
                System.Threading.Thread.Sleep(3000)
                scarica_mp3()
            Finally
                Me.Session.Add("download", True)
            End Try


        ElseIf RequestParams("download") = "2" Then
            'questa chiamata viene fatta con ajax per controllare la variabile di sessione download
            'se esiste ed è true dò la direttiva al client di togliere il messaggio di attesa
            Dim risposta As New json()

            Dim o As Object = Me.Session("download")
            If o Is Nothing OrElse CBool(o) = False Then
                risposta.Add("download", False)
            Else
                risposta.Add("download", True)
                Me.Session("download") = Nothing
            End If

            Response.Write(risposta.ToJson)
            Response.End()

        End If

    End Sub

    Private Sub scarica_mp3()
        'Download stringa rtf

        Dim messaggioErrore As String = ""
        Dim filePath As String = ""
        Dim fi As FileInfo = Nothing

        Try
            filePath = Me.Server.MapPath("Track01.mp3")
            fi = New FileInfo(filePath)
            If Not fi.Exists Then
                Throw New Exception("file non esistente")
            End If

            If RequestParams("cb_errore") = "on" Then
                Throw New Exception("Errore provocato per prova")
            End If

        Catch ex As Exception
            messaggioErrore = ex.Message
        End Try
        
        If messaggioErrore = "" Then
            ' imposta le headers 
            Response.Clear()
            Response.AddHeader("Content-Disposition", "attachment; filename=""" & fi.Name & """")
            Response.AddHeader("Content-Length", fi.Length.ToString())
            Response.ContentType = "application/octet-stream"

            ' leggo dal file e scrivo nello stream di risposta 
            Response.WriteFile(filePath)
            Response.End()

        Else
            Response.Write(String.Format("<script>alert(""{0}"");</script>", libreria.toStringaJS(messaggioErrore)))
            Response.Flush()
            Response.End()

        End If

    End Sub

End Class

ps. guardando bene, ci sono dei commenti "strani". Sono residui di un altro problema; e non ho corretto.