Henryk Plötz: Überwachung eines Datei-Upload via HTTP

Beitrag lesen

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:

  • Erstelle ein PHP-Skript das eine hochgeladene Datei entgegen nimmt sowie ein passendes Upload-Formular und lade das Formular im Browser.
  • Kille den Apache und starte ihn im Debug-Modus über strace ([1]), etwa so
    strace /usr/sbin/httpd -X 2>&1 | tee logdatei
  • Warte bis der Apache bereit ist (dann sollte strace sowas wie accept(16,  evt. mit anderer Zahl ausgeben)
  • Lade eine x-beliebige Datei im Browser hoch.
  • beende strace und den Apachen (Strg-C) und schau dir die generierte Logdatei an.

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