Andreas Korthaus: Datei erstellen -> danach zum Download anbieten

Beitrag lesen

Hi!

ich erzeuge auf meiner Webseite Pdf Dokumente per PHP. Das dauert leider gerne mal 30-60 Sekunden. Die Dateien werden nach der Erstellung heruntergeladen. Nun mein Problem ist, das ich nicht 30 Sekunden und mehr einen leeren Bildschirm zeigen möchte. Am liebsten wäre es mir die Ergebnis Seite auszugeben mit einen "Bitte warten" Text und sobald diese Dateien fertig erstellt worden sind diesen Text durch den Link zu den Dateien ersetzen. Ich suche dazu eine Lösung oder einen Ansatz weil irgendwie habe ich dazu keine wirklich brauchbare Idee.

Du hast das Problem, das Du meines Wissens nicht so ohne weiteres die TCP-Verbindung zwischen Server und Browser aus PHP kontrollieren kannst. Das heißt, Du kannst nicht einfach den HTML-Code vorab zum Browser schicken (z.B. inkl. Ajax-Code, der in einer Schleife ein anderes Script abfragt ob die Datei fertig ist...), die TCP-Verbindung schließen, das PDF erstellen und wenn per Ajax gemeldet wird, dass die Datei fertig ist, wird per Javascript der Link angezeigt. Da Du die Verbindung nicht vor Ende des Scripts serverseitig trennen kannst, hast Du keine Kontrolle über verschiedene Puffer und Caches, die möglicherweise verhindern, dass Deine "bitte warten" Seite auch tatsächlich angezeigt wird (wenn das bei Dir funktioniert, muss das noch lange nicht bei allen anderen Besuchern funktionieren).

Als Workaround kannst Du z.B. mit flush() versuchen sämtliche Puffer zu leeren bevor Du mit dem Generieren des PDFs anfängst, aber 100% klappt das nicht überall (siehe Manual-Kommentare zu flush()). Das könnte dann z.B. so aussehen:

  
<html>  
<body>  
  <div id="wait">Bitte warten...</div>  
  <div id="link" style="display:none">Fertig: <a href="./datei.pdf">download</a></div>  
  
<?php  
  flush();  
  sleep(5); // alternativ was sinnvolles machen...  
?>  
  
  <script type="text/javascript">  
    document.getElementById("wait").style.display = "none";  
    document.getElementById("link").style.display = "";  
  </script>  
</body>  
</html>  

Alternativ könnte man auch versuchen per header() vor der Generierung auf eine "bitte warten" Seite umzuleiten, die wiederum per Ajax prüft wann das PDF fertig ist. Allerdings kann es hierbei passieren, dass die Umleitung erst ausgeführt wird, wenn das PDF fertig ist.

  
<?php  
  ignore_user_abort();  
  header('Location: http://example.com/bitte_warten.html');  
  ob_flush_end();  
  flush();  
  sleep(5); // alternativ was sinnvolles machen...  
?>  

Eine zuverlässigere aber auch deutlich kompliziertere Lösung wäre, einen Dämon zu schreiben, dem Du im aufgerufenen PHP-Script irgendwie die notwendigen Informationen übergibst, der dann das PDF generiert. Man könnte z.B. per Socket kommunizieren, oder der Prozess überwacht ein Verzeichnis in das Du die "Aufträge" legst... dann müsstest Du jedenfalls nur die Daten übergeben und könntest direkt die "bitte warten" Seite ausgeben, was dann zu 100% funktioniert da die TCP-Verbindung nach Übergabe der Daten und Senden des HTML-Codes beendet wird. Auf der ausgelieferten HTML-Seite könntest Du dann mit Ajax wieder ein Script aufrufen, welches Dir sagt ob die Datei bereits zum Download bereit steht oder nicht.

Eine bessere Lösung ist mir nicht bekannt. Die dritte Variante wird in den meisten Fällen aufgrund von technischen Beschränkungen nicht möglich sein, dann muss man entweder mit den Problemen der ersten beiden Variante leben (bzw. so gut wie möglich drum herum arbeiten), oder halt drauf verzichten und vorher dem Besucher gegenüber eine entsprechende Ankündigung machen.

Grüße
Andreas