Oftmals möchte man ein "Bitte warten..." mit einer Animation anzeigen, während dem eine Datei auf dem Server dynamisch generiert und dann heruntergeladen wird.

Das Problem hierbei ist, dass man nicht weiss wann der Download beginnt (Browser zeigt Download Dialog) und man die Animation wieder stoppen muss.

Einen simplen aber effektiven Trick dafür habe ich auf folgender Seite gefunden: http://gruffcode.com/2010/10/28/detecting-the-file-download-dialog-in-the-browser/

Ganz einfach zusammengefasst funktioniert es folgendermassen:

  • Ein Klick auf einen Download-Link zeigt eine Animation an und führt einen Postback aus
  • Gleichzeitig wird clientseitig ein Timer gestartet der alle 500ms prüft ob ein bestimmtes Cookie vorhanden ist
  • Ist das Cookie vorhanden, wird die Animation wieder ausgeblendet
  • Serverseitig wird die Datei die heruntergeladen werden soll dynamisch erstellt und direkt in die HTTP Response geschrieben
  • Zusätzlich wird auch das oben erwähnte Cookie in die Response geschrieben
  • Sobald der Browser die Antwort des Servers erhält, wird der Download-Dialog angezeigt und gleichzeitig das Cookie gespeichert
  • Der clientseitigt JavaScript Timer läuft dabei im Hintergrund weiter, erkennt das Cookie und blendet die Animation aus

Beispielimplementierung einer ASP.NET MVC View:

<div>
    @using (Html.BeginForm("Download", "Home"))
    {
        @Html.Hidden("cookieValue")
        
    }
</div>

@section scripts {
<script>
    var _tmr;
    $(function () {
        $('#btnDownload').click(function () {
            $('#cookieValue').val(Date.now().toString());
            $('#divAnimation').show();

            _tmr = window.setInterval(function () {
                var _str = 'dlc=' + $('#cookieValue').val();
                if (document.cookie.indexOf(_str) !== -1) {
                    $('#divAnimation').hide();
                }
            }, 500);
        });
    });
</script>
}

Und die Implementierung des Controllers:

[HttpPost]
public FileResult Download(string cookieValue)
{
    System.Threading.Thread.Sleep(5000);
    string content = "Das ist meine Datei.";            
    ControllerContext.HttpContext.Response.Cookies.Add(
        new HttpCookie("dlc", cookieValue));
    return File(System.Text.Encoding.ASCII.GetBytes(content),
        "text/plain", "dateiname.txt");
}

Damit das Ganze auch mehrfach hintereinander funktioniert, muss jedes Mal auf einen neuen eindeutigen Wert des Cookies geprüft werden. Dazu wird ein Timestamp generiert und in einem Hidden-Field im POST Request an den Server übermittelt. Der Server setzt dann das Cookie mit diesem Wert.