Nachdem ich entdeckt habe, dass in diesem Forum noch jemand über die genaue Funktionsweise der Fortschrittsbalkenanzeige über PHP etwas wissen möchte, gehe ich hier nochmal ergänzend zu den Erklärungen in dem Artikel über die Installation und Benutzung zur Fortschrittsbalkenanzeige ein.
Diese Beschreibung bezieht sich dann jedoch nicht nur auf den PHP-Datei Upload sondern auf jegliche Techniken, die den Fortschritt des Uploads, der über das HTML-Formular-Element input/File überwachen. Also auch jene CGI, C oder Perl-Lösungen.
Erst einmal grundsätzlich, was passiert dort. Man lädt eine Datei hoch. Während dessen muss irgendwie auf dem Server abgefragt werden, wieviel der Datei bereits gesendet wurde. Optimalerweise hat man auch schon die Information wie groß die Datei ist, die gesendet wird. Somit kann man über den bisherigen Fortschritt und die Dateigröße sowie die verstrichene Zeit in etwa berechnen, wie lange der Upload noch dauern wird. Außerdem kann man herausfinden, wie schnell die Upload-Geschwindigkeit im Mittel ist.
Diese Informationen müssen dem Benutzer angezeigt werden. Und das kann nur passieren, indem der Browser alle X Sekunden, möglicherweise sogar jede Sekunde eine Seite auf dem Server abfragt und dann dem benutzer grafisch anzeigt, was der Server berechnet hat. Wer hier an Server-Requests sparen will, kann leider nicht mitspielen. Egal was man benutzt, ein Request pro Informations-Schritt muss drin sein. Jedoch kann man durch entsprechende Techniken die Größe der zurückgegebenen Daten minimieren. So ist es natürlich auf der einen Seite möglich, eine komplette HTML-Seite nebst dem entsprechendem Verweis auf die richtige Grafik zurückzugeben. Wenn man richtig mit was ausrichten will (im negativen Sinne auf die Performance bezogen) kann man gar ein Bild zurückgeben, erstellt durch die GDLib. Aber das würde jetzt zu weit führen und ist wie wahrscheinlich schon bemerkt wurde, das negativ-Beispiel. Das Mittel ist wie gesagt, eine HTML-Seite zurückzugeben. Am meisten Ressourcen spart man jedoch, zumindest bezogen auf die Größe der zurückgegebenen Daten bei jedem Request, wenn man Ajax benutzt. So reicht es per Ajax genau 3 Zahlen zurückzugeben: Dateigröße, bisher hochgeladene Bytes, verstrichene Zeit. Alles weitere kann man im Zweifel auch per JavaScript berechnen. Klar, ob es jetzt etwas ausmacht, 2 weitere Zahlen mit auszugeben, muss sich jeder selbst überlegen.
Und dann? Dann setzt man die Zahlen ein. Ein bisschen berechnen, ein bisschen Prozentrechnung Wieviel Pixel meines 200 Pixel langen Balkens müssen rot werden, wenn 10 von 100 KB bereits hochgeladen wurden? Genau, 20. mit document.getElementById(‘balken’).style.width=20px; setzt man dann zum Beispiel diesen Wert. Und bei jedem Request rechnet man erneut und passt die Werte wieder an.
Auf einen, sagen wir mal Irrglauben wollen wir noch kurz eingehen. Es wird dann manchmal gesagt “Dass die Seite X mal refresht wird um den Status anzuzeigen, das will ich nicht”. Klar, wie oben beschrieben, muss das nicht sein. Man kann es wie beschieben Ressourcen-sparender machen. Aber ob der Unterschied lohnenswert ist muss jeder selbst entscheiden. Denn wie beschrieben, ist ein Ajax-Call genauso ein request, als würde man eine Seite neu laden. Nur dass bei Ajax eben nur bestimmte Elemente neu geladen werden oder Zahlen für eine JavaScript-Berechnung herein geholt werden. Der Header der HTTP-Anfrage, der auch mal genauso groß sein kann, wie die Seite die ausgegeben wird, wird auch bei einem Ajax-Call mitgeschickt – ganz HTTP eben.
Ein Problem, das aufkommt, wenn man diese Fortschrittsbalken realisieren möchte ist, dass während dem Upload über ein Formular auf der selben Seite quasi nichts mehr geht. Man kann also auf der selben Seite erstmal nichts per Ajax verändern, denn dieses Fenster ist während dem Upload blockiert. Man kann auch nicht auf einem IFrame der sich auf dieser Seite befindet zugreifen.
Also bleibt entweder ein Popup-Fenster zu öffnen. Das ist aber eher unbeliebt, wird von den Browsern von hause aus geblockt und fällt im Zweifel, wenn es denn da ist eher nicht so auf. Deswegen gibt es den Trick, das Upload-Formular in einen IFrame zu posten. Somit ist das eigentliche Fenster nicht blockiert und kann den Status ausgeben.
Eine Seite, auf der der Upload mit einem schönen Fortschrittsbalken realisiert wurde ist übrigens wohin-heute.net. Dort sieht man auch, dass mehrere Hundert Megabyte kein Problem für die Fortschrittsbalken-Anzeige sind. Das einzige Unschöne ist, dass wenn die Dateigröße dann doch einmal die angegebenen Werte von upload_max_filesize oder post_max_size überschreiten, kein Fortschrittsbalken angezeigt wird. Es ist aber auch nicht direkt ein Fehler zu erkennen. Somit lädt der Benutzer im Zweifel 2 Stunden etwas hoch, bevor ihm gesagt wird, dass die Datei zu groß war
1 Kommentar
Hallo wolke,
hast Du eine Ahnung wie genau das bei wohin-heute.net realisiert wurde? Deine Demo vom anderen Eintrag funktioniert bei mir seht gut, aber ich hätte die Progressbar auch lieber auf der Uploadseite mit eingebunden, statt eines neuen Fensters; letztendlich so wie es bei wohin-heute.net gemacht ist. Bin hier total am verzweifeln.
Hat irgendjemand einen Samplecode dafür?
Liebe Grüße
HOgi