Timing Problem beim JS gesteuerten Download?

Sprint

Erfahrenes Mitglied
Hallo zusammen,

gestern hatte ich ein Thema zum automatischen Download im PHP Bereich, das letztendlich per JS gelöst werden konnte. Dabei wird dieses Script FileSaver.js verwendet.

Beim Testen mußte ich dann aber leider feststellen, daß nicht immer alle Dateien geladen werden. Ich vermute da ein Timingproblem mit dem Browser, weshalb ich dann ein Timeout von zwei Sekunden eingebaut habe. Daraufhin wurde es besser, aber es passiert immer noch, daß eine Datei übersprungen wird.
Merkwürdigerweise werden die Ergebnisse aber auch wieder schlechter, wenn ich die Zeit z.B. auf 5 Sekunden erhöhe. Andererseits habe ich aber auch den Eindruck, als ob nur bei der ersten Datei gewartet würde.
Javascript:
    function download_all(fileidx){
        const files = [];
<?php
    echo 'files[0] = '.json_encode($allfiles_files).";\r\n";
    reset($npfiles_files);
    foreach ($npfiles_files as $n => $npz)
        echo 'files['.$n.'] = '.json_encode($npz).";\r\n";
?>
        const path = '<?php echo $allfiles_pfad; ?>';
        files[fileidx].forEach(file => {
            setTimeout(function() {
                download(path+file, file, {});
            }, 2000);
        });
    }
Zwei Sekunden sollten eigentlich reichen, da wir hier mit einer 250er Leitung arbeiten und die Dateigrößen überwiegend nur im Kilobyte Bereich liegen. Hat da jemand eine Idee dazu, wie es zu den Aussetzern kommen kann und ob man was dagegen machen kann?
 
Lösung
Andererseits habe ich aber auch den Eindruck, als ob nur bei der ersten Datei gewartet würde.
Der Eindruck trifft zu, das ist genau das, was programmiert ist: Die einzelnen Schleifendurchläufe passieren ja quasi gleichzeitig und jedes Mal beträgt die Verzögerung 2 Sekunden. Du kannst das leicht staffeln, indem Du die Verzögerungszeit jedes Mal erhöhst:
Code:
        let delay = 0;
        files[fileidx].forEach(file => {
            setTimeout(function() {
                download(path+file, file, {});
            }, delay);
            delay += 2000;
        });
Aber:
1. Verstehe ich nicht, dass Dateien verloren gehen, denn bisher war meine Erfahrung, dass es kein Problem ist, mehrere Anfragen quasi gleichzeitig an den Server zu...
Jetzt hatte ich wieder mal einen Aussetzer. Fünf Dateien sollten geladen werden. Beim ersten Mal waren es nur zwei, dann alle fünf und beim dritten Mal drei. Alles innerhalb von drei Minuten. Und wie ich befürchtet hatte, keine Fehlermeldung. Im Netzwertab waren Zugriffseinträge für alle fünf Dateien. Der Server selbst hat im Protokoll aber keine Einträge über unterbrochene Verbindungen.
Ich habe das dann noch ein paar Mal probiert, aber immer das selbe. Mal zwei, Mal fünf, ganz unterschiedlich. 17 andere Dateien, aus dem selben Verzeichnis, werden hingegen alle korrekt geladen. Es sieht völlig willkürlich aus.
 
Mal versuchen, im fetch Fehler abzufangen. Ich bin unterwegs und habe nur das Handy. Vielleicht nimmt sich jemand anders der Sache an.
 
Ich habe das Errorhandling mal in die vorhandene Funktion eingetragen:
Code:
    function download_all(fileidx){
        // Eine Datei herunter laden und speichern:
        function downloadOne(idx) {
            // Die aktuelle Datei mit fetch herunter laden:
            fetch(path + currentFiles[idx]).then(response => {
                if (!response.ok) {
                    throw Error(response.statusText);
                }
                return response.blob();
            }).then(blob => {
                // Der Parameter blob enthält die herunter geladene Datei.
                // Wir speichern sie im lokalen Dateisystem:
                saveAs(blob, currentFiles[idx], {});
                // Existiert eine weitere Datei?
                if (currentFiles[idx + 1]) {
                    // Herunterladen dieser Datei veranlassen:
                    downloadOne(idx + 1);
                }
            }).catch(function(error) {
                console.log(error);
            });
        }
        const files = [];
        files[0] = ["53-0.JPG","53-1.PDF"];
        files[1] = ["53-NP1-0.PDF","53-NP1-1.PDF"];
        files[2] = ["53-NP2-0.JPG","53-NP2-1.PDF","53-NP2-2.PDF"];
        // Die Gruppe von Dateien, die aktuell herunter geladen werden sollen,
        // bereit stellen:
        const currentFiles = files[fileidx];
        const path = '../pruefpdf/74394/74394199/';
        // Das Herunterladen mit der ersten Datei beginnen:
        downloadOne(0);
    }
(ungetestet)
Quelle:
Handling Failed HTTP Responses With fetch()
Versuche, ob das irgend welche Hinweise liefert.
 
Das ganze wird immer merkwürdiger. Wir hatten gerade eben wieder den Fall, daß zwei Dateien von insgesamt sechs nicht heruntergeladen wurden. Der Browser hat aber keine Fehlermeldung registriert. Im Netzwerktab waren alle sechs Dateien als ordnungsgemäß geladen aufgeführt und auch das Serverprotokoll bestätigt das.
 
Dann liegt das Problem anscheinend nicht beim Herunterladen sondern beim Speichern. Ich habe da noch etwas weiter gesucht und dies gefunden:
Allow Multiple File Downloads in Safari
Safari didn't like that the button was being pressed more than one time a second, it registered that the data was there and everything had updated but it only ever triggered the last download, setting a delay between file downloads allowed enough time for Safari to process that there should be multiple files downloaded.
Wahrscheinlich benutzt unser saveAs einen Hilfsbutton und Safari lässt nicht zu, dass der schnell hintereinander gedrückt wird. Dann waren wir bisher auf der falschen Spur, denn wenn die Dateien relativ klein sind, ist das Herunterladen schnell beendet. Wir sollten zu der Lösung mit dem durch setTimeout gestaffelten Herunterladen zurück gehen. Du hattest den Code in Posting #5 gepostet. Vielleicht durch ein console.log prüfen, ob die Staffelung richtig funktioniert.
 
Ich hatte inzwischen auch schon unsere Security darauf angesetzt. Vielleicht waren ja Bitdefender oder Sophos daran Schuld. War aber auch nichts zu finden. Eine Kollegin testet jetzt das ganze mal im Chrome. Wenn es da geht, dann würde das die Safari Theorie stützen. Werde morgen dann wieder die alte Fassung nochmal probieren.
 
Bei Chrome hat das Script funktioniert, aber meine Kollegies nutzen lieber Safari. Und da scheint es mit dem älteren Script zu funktionieren. Zumindest hatten wir in den letzten zwei Stunden keine Aussetzer mehr. Wenn das den Rest des Tages so bleibt, werde ich ab morgen mal versuchen, die Zeit zu reduzieren. Zwei Sekunden sind schon ziemlich lange und eine Kollegin ist sehr ungeduldig.

Ja, es funktioniert jetzt tatsächlich. Vielen Dank nochmal für deine Hilfe!
 
Zuletzt bearbeitet:
Zurück