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...
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 schicken.
2. Ist eine feste Verzögerung immer ungünstig, besser ereignisgesteuert arbeiten und die nächste Anfrage erst schicken, wenn die Antwort für die vorige da ist.

Interessante Sache, ich werde beides mal untersuchen.
 
Lösung
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 schicken.
2. Ist eine feste Verzögerung immer ungünstig, besser ereignisgesteuert arbeiten und die nächste Anfrage erst schicken, wenn die Antwort für die vorige da ist.
Die Dateien wurden bisher alle einzeln aufgeführt. Aber auch da kam es zu Aussetzern, wenn die Links zu schnell nacheinander angeklickt wurden. Besonders eine Kollegin maust schneller als ihr Schatten, und ihr passierte das öfters.

Ich hatte bei FileSaver auch nach einem Rückgabewert gesucht, konnte da aber leider nichts finden. Darum blieb mir nur die feste Verzögerung.
 
FileSaver hat auch eine Funktion saveAs, wir können die Dateien mit fetch herunter laden und mit diesem saveAs lokal speichern. Dann ist es kein Problem, das Ganze ereignisgesteuert ablaufen zu lassen:
Code:
        const files = <?php echo json_encode($files); ?>;

        function downloadOne(idx) {
            fetch(files[idx]).then(response => {
                return response.blob();
            }).then(blob => {
                saveAs(blob, files[idx], {});
                if (files[idx + 1]) {
                    downloadOne(idx + 1);
                }
            });
        }
        downloadOne(0);
 
Da bin ich jetzt etwas überfordert.
Ich hatte das Script gestern noch so erweitert, daß mehrere Download-Gruppen mit einer Funktion verarbeitet werden konnten. Bisher sah das dann z.B. so aus.
Javascript:
    function download_all(fileidx){
        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"];
        const path = '../pruefpdf/74394/74394199/';
        let delay = 0;
        files[fileidx].forEach(file => {
            setTimeout(function() {
                download(path+file, file, {});
            }, delay);
            delay += 2000;
        });
    }
Beim Aufruf der Funktion mit z.B. 1 wurden die Dateien runtergeladen, die unter files[1] eingetragen waren.
Der Pfad ist bei allen Gruppen gleich, ändert sich aber je nach Vorgang. Deshalb muß der auch variabel sein. Wie bringe ich das jetzt mit der neuen Variante zusammen?
 
Hat denn das mit der Staffelung durch das delay+=2000 eine Verbesserung gebracht?

Beide Skripts zusammen geführt müssten so aussehen:
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 => {
                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);
                }
            });
        }
        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);
    }
Dies jetzt ungetestet. Wenn Du es nicht zum Laufen bekommst, werde ich selber eine Testumgebung einrichten.
 
Ich hatte das geänderte Script hochgeladen, aber es gab wohl keinen Fall, bei dem sich das ausgewirkt hätte. Und auch bei älteren Fällen ist es ja nicht immer gleich. Mal trat es auf, mal nicht.

Die zusammengeführte Funktion läuft auf jeden Fall. Ich werde das mal unseren Leuten zur Beobachtung geben. Ein Ergebnis wird aber erst morgen kommen.

Auf jeden Fall bis hier hin schon mal vielen Dank für deine Unterstützung.
 
PS: Ein Rätsel hat sich auch aufgeklärt: In meinem Browser, Opera, kann ich einstellen ob beim Herunterladen nach dem Speicherort gefragt wird. Deaktiviere ich das, wird, genau wie bei dir, sofort ohne Nachfrage herunter geladen in das Verzeichnis, das ich in den Einstellungen ausgewählt habe.
 
Zuletzt bearbeitet:
Ich habe jetzt einige Reaktionen meiner Kollegen. Das ist alles sehr merkwürdig. Es gibt immer noch Aussetzer, die ich aber auf meinem Rechner nicht nachvollziehen konnte. Komischerweise sind es auch immer die selben Dateien, die nicht geladen werden. An der Dateigröße liegt es nicht und an der Datei selbst auch nicht. Einzeln wird die sofort geladen. Der Dateityp war immer ein PDF, oftmals sogar aus der selben Quelle.
 

Neue Beiträge

Zurück