Nico R.: SESSION steht in fetch-Datei nicht zur Verfügung

Hallo zusammen,

aufbauend auf eurem Tutorial zum File Upload möchte ich gerne auch einen Fortschrittsbalken anzeigen. Ich scheitere allerdings daran, per fetch die SESSION zum Upload anzuzeigen. Hier kurz der grobe Ablauf bis zu der Stelle, wo es hakt.

Formulardatei:

<form id="galerie_upload" method="post" enctype="multipart/form-data">
  <input type="hidden" name="progress" value="galerie">
  ...
</form>
...
$_SESSION["test"] = "test";

Absenden der Formulardaten per fetch:

const progress = document.querySelector('[name="progress"]').value;
...
formData.append('<?=ini_get("session.upload_progress.name")?>', progress);
...		
fetch("sql/galerie_upload.php", {
  method: "POST",
  body: formData
...

galerie_upload.php:

session_start();

echo "<pre>";
var_dump($_POST);
echo "</pre>";

echo "<pre>";
var_dump($_SESSION);
echo "</pre>";

Antwort von galerie_upload.php:

array(1) {
  ["PHP_SESSION_UPLOAD_PROGRESS"]=>
  string(7) "galerie"
}

array(2) {
  ["test"]=>
  string(4) "test"
}

Dort wird also die SESSION mit dem Test-Eintrag erstellt und auch das POST wird korrekt übertragen. Den SESSION-Eintrag zum progress hatte ich hier noch nicht erwartet. Den wollte ich mir mit einem timeout per weiterem fetch anzeigen lassen:

Anzeigen der progress-SESSION per fetch:

function progress_timeout() {		
		
  fetch("sql/galerie_upload_progress.php").then((response) => {
    console.log(response);
  });		
		
  window.setTimeout(function() {
    console.log("progress...");
    if(!fertig) { // globale Variable. Wird auf true gesetzt in galerie_upload.php
      progress_timeout();
    }
    else {
      clearTimeout(this);
      return;
    }
  }, 1000);
}
		
window.setTimeout(progress_timeout,1000);	

galerie_upload_progress.php:

session_start();

echo "<pre>";
var_dump($_SESSION);
echo "</pre>";

Antwort aus galerie_upload_progress.php:

array(0) {
}

In dieser zweiten fetch-Datei steht die SESSION also plötzlich nicht mehr zur Verfügung. Wieso ist das so? Hat jemand eine Idee? Ich hoffe, das war nicht zu viel Code. Ich habs so weit es ging, kurz gehalten.

Schöne Grüße

Nico

  1. Hallo Nico,

    TIL: PHP bietet Upload-Monitoring an 😀

    Frage 1: Bist Du sicher, dass der POST nach einer Sekunde noch läuft? Vielleicht ist PHP ja schon fertig?

    Frage 2: Ist das Request-Buffering des Webservers deaktiviert oder hinreichend klein? Grund: Wenn der Server erstmal alles puffert, bevor er PHP die Kontrolle übergibt, bekommt PHP den ganzen Kram auf einen Rutsch und kommt gar nicht dazu, einen Fortschritt zu messen

    Frage 3: Hast Du überprüft, dass der fetch auf sql/galerie_upload_progress.php den gleichen Session-Cookie verwendet, der auch für galerie_upload benutzt wird? Ansonsten sind das zwei verschiedene Sessions.

    Ich müsste mir das Ganze jetzt mit PHP/JS nachbauen, um mehr sagen zu können.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      danke erstmal für deine Hilfe.

      TIL: PHP bietet Upload-Monitoring an 😀

      Was meinst du damit? Bin ich auf einem falschen Weg? Nach der Suche nach TIL bin ich etwa genauso schlau wie vorher 😀

      Frage 1: Bist Du sicher, dass der POST nach einer Sekunde noch läuft? Vielleicht ist PHP ja schon fertig?

      Naja, ich habs zumindest mit einer 20 MB großen Datei getestet. Der Request an galerie_upload.php wird gesendet und dann jede Sekunde der an galerie_upload_progress.php, etwa fünfmal, bis der response.status === 200 das Script stoppt.

      Frage 2: Ist das Request-Buffering des Webservers deaktiviert oder hinreichend klein? Grund: Wenn der Server erstmal alles puffert, bevor er PHP die Kontrolle übergibt, bekommt PHP den ganzen Kram auf einen Rutsch und kommt gar nicht dazu, einen Fortschritt zu messen

      Eieiei, jetzt auch noch Serverkonfiguration. Wie finde ich das denn heraus? Es klingt so, als wäre das keine PHP-Einstellung und damit auch kein Wert in der php.ini?

      Frage 3: Hast Du überprüft, dass der fetch auf sql/galerie_upload_progress.php den gleichen Session-Cookie verwendet, der auch für galerie_upload benutzt wird? Ansonsten sind das zwei verschiedene Sessions.

      Mit credentials: "include" in fetch() wird die $_SESSION jetzt auch in der galerie_upload_progresss.php angezeigt. Allerdings ist dort nach wie vor keine Spur von einem progress-Eintrag. Hm...

      Ich müsste mir das Ganze jetzt mit PHP/JS nachbauen, um mehr sagen zu können.

      Das wäre auch zu viel verlangt. Mir hilft das hier erstmal schon ungemein. Sollte ich überhaupt nicht mehr weiterkommen, werd ich gerne noch ein Testscript auslagern und hochladen. Also vermutlich morgen 😀

      Schöne Grüße

      Nico

      1. Hallo Nico R.,

        TIL: PHP bietet Upload-Monitoring an 😀
        Was meinst du damit?

        TIL = Today I Learned… - mit anderen Worten: das kannte ich noch gar nicht.

        Bin ich auf einem falschen Weg?

        Möglicherweise. Die Alternative ist ein clientseitiges Monitoring ohne PHP zu befragen. Dann weißt Du immerhin, wieviele Bytes Du geschickt hast, wenn auch nicht, wieviele Bytes in PHP angekommen sind (die Differenz ist gerade auf dem Draht unterwegs und in diversen Datenpuffern). Hypothetisch geht das mit einem einzigen fetch()-Aufruf, ABER nicht mit FormData als Body. Du brauchst einen ReadableStream, denke ich, um die Häppchen mitzubekommen, die er überträgt, und die Beispiele, die ich dazu gefunden habe, sind alles andere als einfach.

        Was Felix anspricht, ist ein handgemachtes Segmentieren des Uploads im JavaScript (→ File API), handgesteuertes Hochladen der Segmente mit einzelnen POST-Requests und ein handgemachtes Einsammeln und Zusammensetzen der Segmente im PHP. Das ist auch nicht so einfach, aber zumindest hast Du dann den Fortschritt komplett in eigener Kontrolle.

        Grundsätzlich sollte PHP aber auch den von Dir versuchten Weg liefern können, aber die Voraussetzung, dass die Webserver-Software nicht buffert, sondern PHP das Einlesen überlässt, ist schon wichtig. Wie man das einstellt? Hängt vom Webserver ab. Was man einstellen muss, auch. Wenn's ein Apache ist - der hat eine umfangreiche Online-Doku. Die müsste ich jetzt auch erst studieren.

        Wieso die Credentials geholfen haben, ist mir schleierhaft. Arbeitest Du mit HTTP- oder Forms-Anmeldung? Was ich meinte, war ein Blick in das Netzwerk-Tab der Entwicklerwerkzeuge, da siehst Du, was er pro Request an HTTP Headern auf den Draht schickt und zurückbekommt (da sind die Cookies und so'n Zeug drin).

        Sorry, dass das Debuggen dieses Ablaufs so ein Rundumschlag ist, aber das ist nunmal ein komplexes Ding, das Du da zum Fliegen bringen willst, und da muss alles zusammenpassen.

        Rolf

        --
        sumpsi - posui - obstruxi
  2. Lieber Nico,

    in der Vergangenheit waren Uploads mit mehr als 2MB Größe durch ein Limit in den PHP-Einstellungen abgeblockt worden. Mit den Jahren haben die Webhoster dieses Limit immer wieder einmal angehoben, weil die Hardware und der Online-Speicher im Verhältnis immer günstiger wurden.

    Warum erzähle ich Dir das? Weil es einen Sinn hat, einen Datei-Upload von der Browserseite her zu segmentieren, um eben dieses Limit zu umgehen. Das tut man prinzipiell mit JavaScript, welches die Portionierung und den Versand übernimmt - und so in der besten Lage ist, einen Fortschrittsbalken anzuzeigen. In dem von Dir verlinkten Wiki-Artikel hatte ich das Unterkapitel Multiupload per JavaScript unterstützen geschrieben. Seit damals hat sich viel getan, sodass man das dort beschriebene Plupload heute mit reinem JavaScript und so tollen Elementen wie <progress> sehr viel schlanker hinbekommt.

    Ich scheitere allerdings daran, per fetch die SESSION zum Upload anzuzeigen.

    Aus meiner Sicht ist das ein sehr ungünstiger Ansatz, wenn es nur um einen Fortschrittsbalken bei einem Upload geht. Wolltest Du hingegen bei der serverseitigen Weiterverarbeitung einen Fortschrittsbalken realisieren, wäre ein stetiges Abfragen eines PHP-Scripts, welches mittels einer Session auf individuelle Daten zugreifen kann, unumgänglich.

    Liebe Grüße

    Felix Riesterer

    1. Hallo Felix,

      Warum erzähle ich Dir das? Weil es einen Sinn hat, einen Datei-Upload von der Browserseite her zu segmentieren, um eben dieses Limit zu umgehen. Das tut man prinzipiell mit JavaScript, welches die Portionierung und den Versand übernimmt - und so in der besten Lage ist, einen Fortschrittsbalken anzuzeigen.

      Ja, bin ich denn doof? Da ich mich eh gefragt hatte, wie das beim Upload großer Datenmengen aufgrund der PHP-Begrenzung funktionieren soll, hatte ich sogar schon kurzzeitig in diese Richtung gedacht, das aber aus irgendeinem Grund wieder verworfen.

      Ich werde das sobald ichs schaffe, mal versuchen umzusetzen und das Ergebnis dann hier reinsetzen. Vielleicht kann das ja als Vorlage für eine Überarbeitung des Tutorials dienen.

      Schöne Grüße

      Nico