Michael Schröpl: Überwachung eines Datei-Upload via HTTP

Beitrag lesen

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

  • beispielsweise wenn er viele Bilder zu einem HTML-Dokument nachladen
    muß. Inwiefern das der Fall ist, darauf wiederum hast Du nur begrenzten
    Einfluß: Bei Netscape 3 und Opera kannst Du die Zahl der parallelen
    Prozesse einstellen, bei Netscape 4 und M$IE mußt Du nehmen, was deren
    Programmierer für sinnvoll halten.

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.