http-upload tracen / progress bar
ahecht
- php
Ich suche nach einer Möglichkeit, einen mittels http in Gang gesetzten Upload einer größeren Datei zu tracen um den Benutzer am anderen Ende über den Stand der Dinge zu informieren.
Soweit bin ich dabei gekommen: Das Formular, das den Upload in Gang setzt, taugt dazu nicht, da das zugehörige Script erst nach beendetem Upload aufgerufen wird. Also wird per onsubmit ein zweites Script aufgerufen, das nun vor der Aufgabe steht, den Namen der dem Upload zugeordneten temporären Datei herauszubekommen. Und genau hier hänge ich fest. Folgende Fragen sind aufgetaucht:
* Gibt es eine Möglichkeit, den Namen des Tempfiles (in Verbindung mit einer Session) im Voraus festzulegen, ohne am PHP Interpreter herumzubosseln?
* Gibt es u.U. eine (Umgebungs-|PHP-|Server-) Variable, aus der man auf das verwendete Tempfile schliessen kann?
* Gibt es eine Möglichkeit, die id des http-Prozesses des Uploads herauszubekommen und darüber das File zu indentifizieren?
TIA,
Andreas
Hi,
Ich suche nach einer Möglichkeit, einen mittels http in Gang gesetzten Upload einer größeren Datei zu tracen um den Benutzer am anderen Ende über den Stand der Dinge zu informieren.
gerne: Wechsele das Protokoll. Mit HTTP ist das nicht möglich; dort werden die Daten vom Client weggejagt, und erst wenn der Server sie vollständig erhalten hat, wird Dein PHP-Script gestartet. Auf Clientseite gibt es ebenfalls keine Möglichkeit (einfach deshalb, weil sie nicht da ist).
Übrigens hatten schon andere vor Dir die Idee, so was zu tun. Ermittle bitte über das Archiv, ob einer wenigstens den Hauch eines theoretisch möglichen Ansatzes hatte.
Cheatah
Cheatah schrieb:
gerne: Wechsele das Protokoll. Mit HTTP ist das nicht möglich;
Sagen wir besser: mit PHP scheint das nicht möglich zu sein. Mit ASP stellt es nämlich offenbar kein Problem dar.
dort werden die Daten vom Client weggejagt, und erst wenn der Server sie vollständig erhalten hat, wird Dein PHP-Script gestartet.
Das ist mir bekannt und steht in meinem Posting auch drin. Weiterhin schrieb ich auch, dass das kein Problem darstellt. Die Möglichkeit des Wechselns auf ein anderes Protokoll steht in diesem Fall nicht zur Verfügung und ich möchte sie auch nicht diskutieren.
Übrigens hatten schon andere vor Dir die Idee, so was zu tun. Ermittle bitte über das Archiv, ob einer wenigstens den Hauch eines theoretisch möglichen Ansatzes hatte.
Nein. Der einzige Weg, der mir gangbar erscheint, ist in meinem Posting beschrieben und mit konkreten Fragen versehen, auf die, wie es aussieht, keiner eine Antwort zu wissen scheint. :-(
regards,
Andreas
Hoi,
Sagen wir besser: mit PHP scheint das nicht möglich zu sein. Mit
ASP stellt es nämlich offenbar kein Problem dar.
Doch, tut es.
Nein. Der einzige Weg, der mir gangbar erscheint, ist in meinem
Posting beschrieben und mit konkreten Fragen versehen, auf die, wie
es aussieht, keiner eine Antwort zu wissen scheint. :-(
</?m=21793&t=3759>
Gruesse,
CK
Sagen wir besser: mit PHP scheint das nicht möglich zu sein. Mit ASP stellt es nämlich offenbar kein Problem dar.
Doch, tut es.
Du kannst Dich gern vom Gegenteil überzeugen, indem Du Dich z.B. bei http://www.photocase.de anmeldest und ein Bild hochlädst.
regards,
Andreas
Hi,
Ich suche nach einer Möglichkeit, einen mittels http in Gang gesetzten
Upload einer größeren Datei zu tracen um den Benutzer am anderen Ende
über den Stand der Dinge zu informieren.
eine frommer Wunsch.
Mit HTTP wirst Du dabei aber beträchliche Probleme haben.
Soweit bin ich dabei gekommen: Das Formular, das den Upload in Gang
setzt, taugt dazu nicht, da das zugehörige Script erst nach beendetem
Upload aufgerufen wird.
Genau. Das ist HTTP.
Also wird per onsubmit ein zweites Script aufgerufen,
Fein. Der Upload ist inzwischen möglicherweise fertig. Vielleicht auch
nicht. Nur: Eine Kontrolle irgend einer Art hast Du darüber nicht.
das nun vor der Aufgabe steht, den Namen der dem Upload zugeordneten
temporären Datei herauszubekommen.
Wie kommst Du darauf, daß der Upload eine temporäre Datei verwendet?
Das _könnte_ natürlich sein. Es muß aber nicht. Bei kleinen Dateien würde
ich es bestimmt nicht tun, wenn ich den Webserver geschrieben hätte.
Das Ziel des "Upload" ist ja nicht, eine Datei auf dem Server zu erzeugen.
Das Ziel ist, es auf dem Server eine Anwendung zu starten, welche den
Inhalt eines CGI-Multipart-Pakets als Parameter erhält. Was diese Anwendung
damit macht, ist ihre Sache - sie kann ihn genauso gut wegwerfen.
Und genau hier hänge ich fest.
Kein Wunder.
* Gibt es eine Möglichkeit, den Namen des Tempfiles (in Verbindung
mit einer Session) im Voraus festzulegen, ohne am PHP Interpreter
herumzubosseln?
Nein. Weder existiert eine solche Datei unbedingt, noch erlaubt Dir HTTP,
darauf in irgend einer Weise Einfluß zu nehmen.
* Gibt es u.U. eine (Umgebungs-|PHP-|Server-) Variable, aus der man
auf das verwendete Tempfile schliessen kann?
Kann ich mir nicht wirklich vorstellen
* Gibt es eine Möglichkeit, die id des http-Prozesses des Uploads
herauszubekommen und darüber das File zu indentifizieren?
Du gehst immer noch davon aus, daß der Upload etwas sei, was er nicht ist.
Passe Deine Vorstellung der Realität an.
HTTP besteht daraus, daß der Client an den Server einen Request sendet
und der Server eine Antwort zurück liefert.
Einfluß auf den Ablauf des Request, insbesondere eine Möglichkeit zur
Reaktion auf irgend einen Ablauf desselben, hast Du nicht.
Etwas Anderes ist es, wenn Du Dein Modell in mehrere Requests zerlegen
könntest.
Ein Browser kann ja durchaus mehrere HTTP-Requests parallel durchführen
Du könntest also _theoretisch_ folgendes versuchen:
1. Du definierst ein Frameset.
2. Du startest den Upload, indem Du einen Submit-Event in einem der beiden
Frames auslöst (Klick auf Button.)
3. Die Submit-Behandlungs-Routine (JavaScript) löst _vor_ ihrer Beendigung
einen Event in dem anderen Frame aus.
4. Danach beendet sie sich und erlaubt dem Formular abgesendet zu werden.
Ab hier läuft der Upload - der Event im anderen Frame ist aber schon in
Bearbeitung!
Der HTTP-Request wird nun irgendwann dazu führen, daß auf dem Server
ein Programm gestartet wird, welches Deine Upload-Datei annimmt - und
vielleicht in einer Datei abspeichert. Vielleicht auch nicht.
Dieses Programm kannst Du selbst schreiben - dann weißt Du, was es tut.
5. In dem anderen Frame läuft nun irgend ein JavaScript-Code von Dir.
Dieser kann ggf. selbst eigene HTTP-Requests zum Server senden.
Er kann insbesondere auf die Formular-Felder im anderen Frame zugreifen.
Vielleicht kann er sogar genügend Informationen sammeln, um herauszu-
finden, was genau dort passiert; vielleicht hätte der onSubmit-Handler
des Upload-Frame ihm vorher auch ein paar Informationen zuspielen können.
Mit etwas Glück könnte er also herausfinden, wie die Datei auf dem Server
heißen soll. Mit etwas Pech reicht es nicht. JavaScript ist nicht meine
Stärke.
6. Mit diesem Wissen könnte der JavaScript-Code also weitere HTTP-Requests
zu einem _anderen_ serverseitigen Skript senden.
Wäre JavaScript eine "richtige" Programmiersprache, dann könnte es sogar
einen HTTP-HEAD-Request auf die entstehende Datei senden - dabei würde
es sowohl deren Existenz als auch deren Größe erfahren. (Vorausgesetzt,
die Datei entsteht innerhalb des URL-Space des Webservers.)
Also zurück zum Machbaren: Dieses Skript würde mit den übergebenen
Parametern berechnen können, wie die zu erstellende Datei auf dem Server
heißen wird. Es kann auch feststellen, ob diese Datei bereits vorhanden
ist; es kann auch ihr letztes Änderungsdatum lesen.
Vor allem kann dieses Skript selbst eine HTML-Seite generieren und an
den Browser zurück senden, welcher sie in dem zweiten Frame darstellt.
7. Diese HTML-Seite enthält nun zwei Dinge:
a) Informationen darüber, was mit der Datei auf dem Server los ist
b) einen META REFRESH-Header, der den Aufruf desselben (!) Skripts mit
denselben Parametern wenige Sekunden später erneut auslöst.
(Ersatzweise <body onload>-JavaScript-Code mit dieser Funktionalität.)
Der zweite Frame "pollt" also den Server, um Informationen über den Stand
der Verarbeitung des ersten Frames zu holen. Sollte der Upload signifi-
kant lange dauern, dann ist er noch nicht fertig. Irgendwann wird auf
dem Server die Datei beginnen, zu existieren; sie wird wachsen und ir-
gendwann aufhören, zu wachsen. Mit sehr viel Glück liegen Deine Polling-
Versuche während einer dieser Phase. Mit etwas Pech siehst Du die Datei
nur plötzlich auf dem Server entstehen.
Was Du alles nicht sehen kannst, ist:
a) einen prozentualen Anteil der Übertragung. Niemand weiß nämlich, wie
groß die Datei am Ende sein wird. Zustandsbalken etc. entfallen also.
b) ein zuverlässiges Ende der Übertragung. Wenn sich der Zustand der
Datei nicht mehr ändert, dann kann das Upload-Skript vielleicht nur
eine Pause machen. Falls sich Deine beiden Skripte auf dem Server aber
gut genug abgesprochen haben, könnte das Upload-Skript etwa die fertige
Datei von x.tmp nach x umbenennen - das wäre für den "Poller" eine
halbwegs brauchbare Information. Und mit dieser kann er sein Polling
dann auch beenden.
Aber was Du eigentlich wolltest, geht mit HTTP nicht.
Dafür bräuchtest Du ein Protokoll, in welchem die Datei häppchenweise
und mit Rückgabe des Kontrollflusses an den Verursacher hochgeladen wird.
FTP wäre ein solches - HTTP nicht.
Viele Grüße
Michael
P.S.: Vielleicht fällt Dir auf, daß meine Ausführungen keinerlei Erwähnung
einer bestimmten serverseitigen Programmiersprache enthielten.
Fein. Der Upload ist inzwischen möglicherweise fertig. Vielleicht auch nicht. Nur: Eine Kontrolle irgend einer Art hast Du darüber nicht.
Doch. In diesem Falle ist das Tempfile, das PHP _definitv_ erzeugt entweder nicht mehr gelockt (Upload ist beendet, aber das entgegennehmende Script ist noch nicht abgelaufen) oder nicht mehr existent, da es nach Ablauf des Scriptes, das vom Upload-Form aufgerufen wurde, gelöscht wird.
Wie kommst Du darauf, daß der Upload eine temporäre Datei verwendet?
1. Es steht im Manual.
2. PHP übergibt dem Script, das den Upload entgegennimmt, den entsprechenden temporären Dateinamen.
Das Ziel des "Upload" ist ja nicht, eine Datei auf dem Server zu erzeugen. Das Ziel ist, es auf dem Server eine Anwendung zu starten, welche den Inhalt eines CGI-Multipart-Pakets als Parameter erhält.
Genau. Im Falle von PHP wird der entsprechende Part eben als temporäre Datei übergeben, d.h. PHP sorgt dafür, dass ein Teil der ankommenden body-Daten des Requests in ebenjener Datei landet.
* Gibt es eine Möglichkeit, den Namen des Tempfiles (in Verbindung mit einer Session) im Voraus festzulegen, ohne am PHP Interpreter herumzubosseln?
Nein. Weder existiert eine solche Datei unbedingt
Siehe oben...
noch erlaubt Dir HTTP, darauf in irgend einer Weise Einfluß zu nehmen.
Hm, ich war wohl etwas undeutlich. Also noch einmal: Es geht - zumindest in dieser Frage - um die Realisierung der im Subject genannten Aufgabe in _PHP_. Und damit kann ich auf einiges Einfluss nehmen (entsprechende Rechte vorausgesetzt).
* Gibt es eine Möglichkeit, die id des http-Prozesses des Uploads herauszubekommen und darüber das File zu indentifizieren?
Du gehst immer noch davon aus, daß der Upload etwas sei, was er nicht ist. Passe Deine Vorstellung der Realität an.
Könntest Du das präzisieren?
Meine Vorstellung vom Vorgang des Multipart-Requests ist es, dass es auf alle Fälle einen Server-Prozess gibt, der den Request und die zugehörigen Daten entgegennimmt. Dieser Prozess reicht die Daten an die im Request genannte Anwendung bzw. deren Handler - in diesem Falle den PHP Interpreter - weiter. Dieser wiederum erkennt, dass der Request im body Daten enthält und speichert diese in einer temporären Datei zwischen, um deren Namen an das aufgerufene Script zu übergeben, sobald die Daten komplett angekommen sind und der Parser mit der Abarbeitung des Scriptes beginnt.
Etwas Anderes ist es, wenn Du Dein Modell in mehrere Requests zerlegen könntest.
Erst lesen, dann posten. Ich zitiere mich mal selbst: "Also wird per onsubmit ein zweites Script aufgerufen[..]". Das _ist_ ein zweiter Request.
Du könntest also _theoretisch_ folgendes versuchen:
[..]
Nichts anderes habe ich bereits beschrieben, wenn auch nicht so ausführlich.
Wäre JavaScript eine "richtige" Programmiersprache, dann könnte es sogar einen HTTP-HEAD-Request auf die entstehende Datei senden - [..]
Es geht hier um PHP. Mir ist schleierhaft, wieso dieser Thread in der Rubrik "HTTP" fortgesetzt wird. Die einzige Stelle, an der Javascript vorkommt, ist das Auslösen des zweiten Requests. Natürlich muss das Tracing serverseitig ablaufen, denn dort passiert ja das, was ich tracen möchte.
[..]Parametern berechnen können, wie die zu erstellende Datei auf dem Server heißen wird.
Nach eben diesen Parametern habe ich gefragt. Nach nichts anderem, denn der Rest ist trivial.
a) einen prozentualen Anteil der Übertragung. Niemand weiß nämlich, wie groß die Datei am Ende sein wird. Zustandsbalken etc. entfallen also.
Der HTTP-Request enthält in der Regel einen Content-Length Header, der von den üblichen Browsern bei Multipart-Daten IMHO auch mitgeschickt wird. Probleme gibt es u.U. damit, von einem paralellen Prozess aus auf diese Daten zuzugreifen ohne root-Rechte zu haben.
b) ein zuverlässiges Ende der Übertragung. Wenn sich der Zustand der Datei nicht mehr ändert, dann kann das Upload-Script vielleicht nur eine Pause machen.
Im Regelfall sind solche Dateien offen, d.h. sie haben ein entsprechendes locking, das sich auch abfragen lässt. Davon abgesehen gibt es ein eindeutiges Signal für einen abgeschlossenen Multipart-Request, da dann mit der Abarbeitung des Scriptes begonnen wird und dieses (z.B. über Shared Memory oder Semaphore) dem zweiten Script (also dem Tracer) Bescheid sagen kann.
P.S.: Vielleicht fällt Dir auf, daß meine Ausführungen keinerlei Erwähnung einer bestimmten serverseitigen Programmiersprache enthielten.
Das ist mir allerdings aufgefallen, aber was sagt mir das? Genau darauf bezog sich meine Frage, weswegen dieser Thread von mir auch unter der Rubrik "PHP" begonnen wurde und nicht unter "HTTP". Keine Ahnung, wie der hierher geraten ist - war da der Forumsgeist am Werk?
regards,
Andreas
Moin
Wie kommst Du darauf, daß der Upload eine temporäre Datei verwendet?
- Es steht im Manual.
- PHP übergibt dem Script, das den Upload entgegennimmt, den entsprechenden temporären Dateinamen.
s.u.
Du gehst immer noch davon aus, daß der Upload etwas sei, was er nicht ist. Passe Deine Vorstellung der Realität an.
Könntest Du das präzisieren?
Meine Vorstellung vom Vorgang des Multipart-Requests ist es, dass es auf alle Fälle einen Server-Prozess gibt, der den Request und die zugehörigen Daten entgegennimmt. Dieser Prozess reicht die Daten an die im Request genannte Anwendung bzw. deren Handler - in diesem Falle den PHP Interpreter - weiter. Dieser wiederum erkennt, dass der Request im body Daten enthält und speichert diese in einer temporären Datei zwischen, um deren Namen an das aufgerufene Script zu übergeben, sobald die Daten komplett angekommen sind und der Parser mit der Abarbeitung des Scriptes beginnt.
Du hast deine Frage doch schon selbst beantwortet: PHP nimmt die Daten entgegen und speichert sie in einer Datei zwischen, nicht der Server. Aus dem was wir bisher wissen, lässt sich nicht sagen dass der Server die hochgeladenen Daten ebenfalls irgendwo zwischenspeichert, und falls ja, wo und unter welchem Namen.
Das die Datei generierende PHP wird nämlich erst aufgerufen nachdem alle Daten erfolgreich übertragen wurden, und genau das nützt dir - wenn ich deine Fragestellung richtig verstehe - herzlich wenig.
Falls du dennoch einen Weg finden solltest dem Server die Infos irgendwie zu entlocken wäre es sehr schön (du könntest dann ja einen Feature-Artikel dazu schreiben, weil ähnliche Anliegen sicherlich mehrere haben), aber meine Vermutung ist, dass es nicht ohne rummfummeln im Quellcode des Apachen gehen wird.
--
Henryk Plötz
Grüße aus Berlin
Du hast deine Frage doch schon selbst beantwortet: PHP nimmt die Daten entgegen und speichert sie in einer Datei zwischen, nicht der Server. Aus dem was wir bisher wissen, lässt sich nicht sagen dass der Server die hochgeladenen Daten ebenfalls irgendwo zwischenspeichert, und falls ja, wo und unter welchem Namen.
Mich interessiert hier auch nur die Datei, die PHP benutzt. Der Server reicht sie, soweit ich weiss, einfach durch. Wenn PHP als Apache-Modul, also im selben Prozess und mit derselben PID, ist da wohl kein Unterschied. Interessant wäre noch der Fall, bei dem PHP als CGI läuft. Ich nehme aber an, dass der httpd in diesem Fall mit einer Pipe arbeitet, so dass die Daten ohne Verzögerung an die verarbeitende Anwendung weitergereicht werden.
Falls du dennoch einen Weg finden solltest dem Server die Infos irgendwie zu entlocken wäre es sehr schön (du könntest dann ja einen Feature-Artikel dazu schreiben, weil ähnliche Anliegen sicherlich mehrere haben), aber meine Vermutung ist, dass es nicht ohne rummfummeln im Quellcode des Apachen gehen wird.
Vom Apache werd ich die Finger lassen, das wäre wohl kaum eine akzeptable Lösung :) Selbst ein externes PHP-Erweiterungsmodul würde nur wenigen etwas nützen, da die meisten auf die PHP Version ihres Providers festgelegt sind.
Aber falls ich etwas finden sollte, wirds auch veröffentlicht.
regards,
Andreas
Moin
Mich interessiert hier auch nur die Datei, die PHP benutzt. Der Server reicht sie, soweit ich weiss, einfach durch. Wenn PHP als Apache-Modul, also im selben Prozess und mit derselben PID, ist da wohl kein Unterschied. Interessant wäre noch der Fall, bei dem PHP als CGI läuft. Ich nehme aber an, dass der httpd in diesem Fall mit einer Pipe arbeitet, so dass die Daten ohne Verzögerung an die verarbeitende Anwendung weitergereicht werden.
Genau, aber die Datei ist für deine Zwecke nutzlos.
Damit ich hier nicht so im luftleeren Raum rumstochere, habe ich eben ein paar Experimente mit Dateiuploads und Apache mit PHP als Modul gemacht.
Soweit ich das beurteilen kann, läuft der Upload so ab:
Lese _alle_ Daten die zur Datei gehören vom Client ein
Erstelle eine temporäre Datei und schreibe die Daten da rein
Lade das PHP-Skript
Ich hab zwar nur mit einer Datei von 23 kB rumgespielt, aber ich glaube kaum dass das Verhalten bei größeren Dateien anders aussehen wird (lasse mich aber gern eines besseren belehren).
Wie du siehst, werden die Daten während sie hochgeladen werden, nirgendwo in eine Datei abgespeichert, du kannst also den Übertragungsvorgang nicht beobachten (naja, ausser du hast root-Rechte und fuhrwerkst im Speicher rum). Die Datei die PHP übergeben kriegt, wird erst erstellt wenn die Daten alle schon da sind. Selbst wenn du also den Namen irgendwie vorher rauskriegen solltest, kannst du immernoch keine Aussage über den Fortschritt des Uploads machen.
Falls du selbst experimentieren möchtest hier noch eine kurze Anleitung:
Da steht dann etwa sowas drin (ziemlich weit am Ende):
accept(16, {sin_family=AF_INET, sin_port=htons(4655), sin_addr=inet_addr("127.0.0.1")}}, [16]) = 5
-- Die Verbindung vom Browser wurde angenommen und hat den Dateideskriptor 5 erhalten.
read(5, "POST /~henryk/senden.php HTTP/1."..., 4096) = 536
-- Es wurden 536 Bytes vom Deskriptor 5 (dem Browser) gelesen
(Wiederholt sich mehrfach, mit anderen Zeilen dazwischen)
read(5, "e Grafikkarte k\366nnen Sie im n\344ch"..., 4096) = 3683
-- Es wurden 3683 Bytes vom Browser gelesen. Da aber bis zu 4096 Bytes erwartet wurden, gehe ich davon aus dass der Upload beendet ist
open("/tmp/php3eSeee", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 7
-- /tmp/php3eSeee wurden zum exklusiven Schreiben geöffnet (und hat Deskriptor 7 gekriegt)
write(7, "<BASE HREF="http://sdb.suse.de/d"..., 20480) = 20480
-- Es wird was (die empfange Daten) in die Temp-Datei geschrieben
close(7)
-- Die Tempdatei wird geschlosssen
open("/home/henryk/public_html/senden.php", O_RDONLY|O_LARGEFILE) = 7
-- Das PHP-Skript wird geöffnet
--
Henryk Plötz
Grüße aus Berlin