misterunknown: AJAX-Fileupload abbrechen

Moin,

ich habe mich gerade mit Möglichkeiten befasst Ajax-Requests abzubrechen, speziell Ajax-Dateiuploads. Ich habe hier diesen Kommentar gefunden, der sagt, dass der Request trotzdem serverseitig weiterverarbeitet wird. Was ist dann im Falle eines Dateiuploads? Wird die "halbe" Datei dann einfach in das Verzeichnis geschoben, oder merkt der Server, wenn die Datei nicht ganz hochgeladen wurde? Gibt es serverseitig eine Kontrollmöglichkeit um zu testen, ob noch eine Response erwartet wird?

Hier etwas Code:

$.ajax({  
	url: ifm.IFM_SCFN,  
	type: "POST",  
	data: data,  
	dataType: "json",  
	xhr: function(){  
		var xhr = $.ajaxSettings.xhr() ;  
		xhr.upload.onprogress = function(evt){ ifm.task_update(evt.loaded/evt.total*100,id); } ;  
		xhr.upload.onload = function(){ console.log('Uploading '+newfilename+' done.') } ;  
		return xhr ;  
	},  
	success: function(data) {  
				if(data.status == "OK") {  
					ifm.showMessage("File successfully uploaded", "s");  
					if(data.cd == ifm.currentDir) ifm.refreshFileTable();  
				} else ifm.showMessage("File could not be uploaded: "+data.message, "e");  
			},  
	error: function() { ifm.showMessage("General error occured", "e"); },  
	complete: function() { ifm.task_done(id); }  
});

Serverseitig behandelt den Request ein einfaches PHP-Skript, welches die hochgeladene Datei in das aktuelle Verzeichnis schiebt.

Grüße Marco

--
Ich spreche Spaghetticode - fließend.
  1. Moin,

    Ich habe hier diesen Kommentar gefunden

    Da war ich zu schnell. Dieser Kommentar.

    Grüße Marco

    --
    Ich spreche Spaghetticode - fließend.
  2. Hallo,

    ich habe mich gerade mit Möglichkeiten befasst Ajax-Requests abzubrechen, speziell Ajax-Dateiuploads. Ich habe hier diesen Kommentar gefunden, der sagt, dass der Request trotzdem serverseitig weiterverarbeitet wird. Was ist dann im Falle eines Dateiuploads? Wird die "halbe" Datei dann einfach in das Verzeichnis geschoben, oder merkt der Server, wenn die Datei nicht ganz hochgeladen wurde?

    Das kommt auf die serverseitige Komponente an. Bei PHP z.B. wird das empfangende PHP-Script m.W. erst ausgeführt, wenn der Multipart-Request komplett eingetrudelt ist und eine vollständige Datei in /tmp erzeugt wurde. Wenn also zwischendrin der Client die TCP-Verbindung schließt und der Request unvollständig ist, dann wird das PHP-Script nie ausgeführt werden. Wenn der Client nach vollständigem Senden die Verbindung schließt, dann wird m.W. das PHP-Script beendet.

    Gibt es serverseitig eine Kontrollmöglichkeit um zu testen, ob noch eine Response erwartet wird?

    Ich bin kein PHP-Spezi, mir ist aber das hier bekannt:
    http://www.php.net/manual/en/function.connection-aborted.php
    http://www.php.net/manual/en/features.connection-handling.php

    Mathias

    1. Moin,

      Ich bin kein PHP-Spezi, mir ist aber das hier bekannt:
      http://www.php.net/manual/en/function.connection-aborted.php
      http://www.php.net/manual/en/features.connection-handling.php

      Danke für die Links, die könnten hilfreich sein.
      Wenn der Request vollständig gesendet wurde, will ich die Verbindung gar nicht mehr unterbrechbar machen (es sei denn der User schließt das Fenster in der Zwischenzeit; allerdings benötigt das Verschieben der hochgeladenen Datei ja nur wenig Zeit, von daher ist es generell schwierig zwischen vollständigem Request und der Reponse die Verbindung zu trennen). Grundsätzlich kann man die Datei dann auch mit der Lösch-Funktion meines Filemanagers löschen. Ich möchte nur, dass der User einen sehr lange dauernden Uploadvorgang abbrechen kann (beispielsweise bei schlechter Internetverbindung).

      Grüße Marco

      --
      Ich spreche Spaghetticode - fließend.
  3. Hi,

    bau mal eine ProgressBar (PB) ein und beobachte den Upload prozentual. Die PB zeigt einen füssigen Upload bis ca 98% und bleibt dann einen kurzen Moment stehen. Du kannst das auch hier beobachten mit einer 2 MB Datei.

    Ich verstehe das so: Die PB monitored das Schreiben in einen Puffer für den HTTP-Request, wenn 98% angezeigt werden, ist das vollbracht und die Daten gehen ab zum Server. Die Verzögerung zwischen 98% und 100% ist die Laufzeit der Response. D.h., wenn ich das richtig verstehe, hast Du ab einem bestimmten Zeitpunkt clientseitig keine Kontrollmöglichkeit mehr, ist der Request einmal raus, läuft der serverseitige Prozess und auf Letzteren hast Du keinen Einfluss mehr (der liest entsprechend Content-Length aus STDIN).

    Möglich also, einen Abbruch VOR dem Senden des Request vorzunehmen, dann gibts auch keine Response.

    1. Moin,

      bau mal eine ProgressBar (PB) ein und beobachte den Upload prozentual. Die PB zeigt einen füssigen Upload bis ca 98% und bleibt dann einen kurzen Moment stehen. Du kannst das auch hier beobachten mit einer 2 MB Datei.

      Eine Progressbar habe ich eingebaut. Ich habe das mal nachvollzogen und tatsächlich - die der Task bleibt bei mir noch eine Zeit lang stehen, wenn 100% erreicht sind.

      wenn ich das richtig verstehe, hast Du ab einem bestimmten Zeitpunkt clientseitig keine Kontrollmöglichkeit mehr, ist der Request einmal raus, läuft der serverseitige Prozess und auf Letzteren hast Du keinen Einfluss mehr (der liest entsprechend Content-Length aus STDIN).
      Möglich also, einen Abbruch VOR dem Senden des Request vorzunehmen, dann gibts auch keine Response.

      Letzteres ist auch gewünscht. Wenn der Upload vollständig ist, will man ja in der Regel nichts mehr abbrechen. Meine Intention ist eher einen Upload, der unerwartet lange dauert (bzw. dauern würde), abbrechen zu können.
      Zusätzlich kann ich ja im PHP-Teil nochmal prüfen, ob die Verbindung noch besteht; das jedenfalls suggeriert der eine Link von molily (function-aborted).

      Grüße Marco

      --
      Ich spreche Spaghetticode - fließend.
      1. Moin,

        bau mal eine ProgressBar (PB) ein und beobachte den Upload prozentual. Die PB zeigt einen füssigen Upload bis ca 98% und bleibt dann einen kurzen Moment stehen. Du kannst das auch hier beobachten mit einer 2 MB Datei.

        Eine Progressbar habe ich eingebaut. Ich habe das mal nachvollzogen und tatsächlich - die der Task bleibt bei mir noch eine Zeit lang stehen, wenn 100% erreicht sind.

        Verstehe die Progressbar, hab auch ne Weile gebraucht ;)

        |<---------------  die gesamte PG ---------->|
        |_________________________________||_________|
        ^ XHR schreibt in den Puffer      ^^ Reponse ^

        Die Anzahl der Bytes sind, bildlich gesehen positiv (senden) oder negativ (empfangen), für den EventHandler wird der |Betrag| genommen.

        Und: Solange geschrieben wird, kommste aus der Geschichte cool wieder raus ;)

        Letzteres ist auch gewünscht. Wenn der Upload vollständig ist, will man ja in der Regel nichts mehr abbrechen. Meine Intention ist eher einen Upload, der unerwartet lange dauert (bzw. dauern würde), abbrechen zu können.

        Geht zu machen.

        Zusätzlich kann ich ja im PHP-Teil nochmal prüfen, ob die Verbindung noch besteht; das jedenfalls suggeriert der eine Link von molily (function-aborted).

        Wäre mal zu testen ;)

        Horst Pilgrim

        1. Hallo,

          Eine Progressbar habe ich eingebaut. Ich habe das mal nachvollzogen und tatsächlich - die der Task bleibt bei mir noch eine Zeit lang stehen, wenn 100% erreicht sind.

          Das ist logisch. Nach dem vollständigen Upload (100%) beginnt die serverseitige Verarbeitung und das Senden der Response.

          Verstehe die Progressbar, hab auch ne Weile gebraucht ;)

          |<---------------  die gesamte PG ---------->|
          |_________________________________||_________|
          ^ XHR schreibt in den Puffer      ^^ Reponse ^

          Nein, das stimmt so nicht. Man könnte eine Progressbar so bauen, aber die progress-Events des XMLHttpRequest-Objektes beziehen sich auf den reinen Daten-Upload, also das Senden des HTTP-Requests. Sie schließen die Serververarbeitung und das Senden der Response nicht ein. Wie auch, hier kennt der Client nicht den Fortschritt und kann auch nicht die Gesamtdauer abschätzen.

          http://www.w3.org/TR/XMLHttpRequest/#make-upload-progress-notifications

          Die Anzahl der Bytes sind, bildlich gesehen positiv (senden) oder negativ (empfangen), für den EventHandler wird der |Betrag| genommen.

          Ich verstehe nicht, was du damit meinst.

          Mathias

          1. hi,

            Verstehe die Progressbar, hab auch ne Weile gebraucht ;)

            |<---------------  die gesamte PG ---------->|
            |_________________________________||_________|
            ^ XHR schreibt in den Puffer      ^^ Reponse ^

            Nein, das stimmt so nicht. Man könnte eine Progressbar so bauen, aber die progress-Events des XMLHttpRequest-Objektes beziehen sich auf den reinen Daten-Upload, also das Senden des HTTP-Requests.

            Da bin ich mir nicht ganz sicher, weil ich anhand der PB in meiner Anwendung was anderes beobachte.

            Serverseitig prüfe ich auf ASCII. Lade ich eine 2 MB ASCII Datei hoch, wird die im Original zurückgesendet, PB

            |__________________________|________________|
                                       ^ 98%            ^ ca 9 Sekunden

            Lade ich jedoch eine 2 MB nicht ASCII-Datei hoch, ist die Reponse viel kleiner (nur ein bischen Text), PB:

            |__________________________|_____|
                                       ^ 98% ^ ca 2 Sekunden

            Daraus folgere ich, dass die PG so arbeitet.

            Wenn die PG jedoch so arbeitet wie DU beschreibst, wäre ich an einer Erklärung interessiert, was die Verzögerung im letzten Stück (der Knick ab 98%) bedeutet.

            Horst

            1. Moin,

              Wenn die PG jedoch so arbeitet wie DU beschreibst, wäre ich an einer Erklärung interessiert, was die Verzögerung im letzten Stück (der Knick ab 98%) bedeutet.

              Bei mir ist es, wie molily beschreibt. Die Progressbar wird bis 100% gefüllt, es dauert einen Moment zum verarbeiten, und dann wird der Vorgang abgeschlossen. Vielleicht nutzt du aber auch eine andere Methode zum Feststellen des Fortschritts? Ich nutze xhr.upload.onproress.

              Grüße Marco

              --
              Ich spreche Spaghetticode - fließend.
              1. hi,

                Bei mir ist es, wie molily beschreibt. Die Progressbar wird bis 100% gefüllt, es dauert einen Moment zum verarbeiten, und dann wird der Vorgang abgeschlossen. Vielleicht nutzt du aber auch eine andere Methode zum Feststellen des Fortschritts? Ich nutze xhr.upload.onproress.

                Logo, ich auch ;)

                Gib mal neben der Bar die Prozente als int aus, Handler

                ``
                    gauge: function(e) {
                        if (e.lengthComputable) {
                            progressBar.value = (e.loaded / e.total) * 100;
                            _('percent').innerHTML = Math.floor((e.loaded / e.total) * 100);
                        }
                    },
                [/code]

                also bei mir sinds, bis aufs Runden, dieselben Zahlen ;)

                Horst

                1. Moin,

                  Gib mal neben der Bar die Prozente als int aus, Handler
                  ``
                      gauge: function(e) {
                          if (e.lengthComputable) {
                              progressBar.value = (e.loaded / e.total) * 100;
                              _('percent').innerHTML = Math.floor((e.loaded / e.total) * 100);
                          }
                      },
                  [/code]

                  Hab ich gemacht. Bei mir rennt er da bis 100 ohne Stocken durch. Allerdings fällt mir gerade an deinem Code auf, dass du auf e.lengthComputable prüfst; das mach ich nicht. Könnte das damit zusammenhängen? Was hat das überhaupt genau zu sagen?

                  Grüße Marco

                  --
                  Ich spreche Spaghetticode - fließend.
                  1. Moin ;)

                    Hab ich gemacht. Bei mir rennt er da bis 100 ohne Stocken durch. Allerdings fällt mir gerade an deinem Code auf, dass du auf e.lengthComputable prüfst; das mach ich nicht. Könnte das damit zusammenhängen? Was hat das überhaupt genau zu sagen?

                    Siehe Link von Mathias. Es wird geprüft, ob es berechenbar ist.
                    Nochmal zu meiner Brettschaltung: 100% werden just in dem Moment ausgegeben, wo die Response angekommen ist. Zeitlich davor verharrt die Gauge bei 98%. Also ich denke schon, dass mit 100% _alles_zusammen, Request und Response gemeint sind.

                    Alles in Allem sollten wir nicht vergessen, dass sich der ganze Kram noch in der Entwicklung befindet womit spätere andere Verhaltensweisen nicht ausgeschlossen sind.

                    Ich für meinen Teil freue mich schon sehr über den ArrayBuffer (danke auch an JürgenB), das ist das, wass ich mir schon vor 10 Jahren gewünscht hatte, um beliebige Datenstrukturen (Binaries) in eine Ajax-Response legen zu können.

                    Wie schrieb schon mein guter Freund Horst J. aus Chemnitz in der Fachzeitschrift "Radio Fernsehen Elektronik" vor gut dreißig Jahren: So manche gute Idee kommt erst zum Tragen, wenn es die Technik hergibt.

                    In diesem Sinne,
                    Alias Horst

                    --
                    MDN
            2. Hallo,

              Wenn die PG jedoch so arbeitet wie DU beschreibst, wäre ich an einer Erklärung interessiert, was die Verzögerung im letzten Stück (der Knick ab 98%) bedeutet.

              Vermutlich eine falsche Implementierung des Standards.

              http://www.w3.org/TR/XMLHttpRequest/#make-upload-progress-notifications sagt klar, dass bei 100% noch einmal ein progress- und ein load-Event geworfen werden muss.

              Davor wird für jeden Byte, aber maximal alle 50ms, ein progress-Event geworfen wird.

              Wenn man keinen progress-Event bei 100% bekommt, dann würde ich zusätzlich auf load hören.

              Mathias