Unregelmäßiger 504 Gateway Timeout Fehler in PHP Skript

TWS

Cadet 4th Year
Registriert
März 2019
Beiträge
89
Hallo zusammen,

ich nutze auf meinem Webspace ein kleines PHP Skript mit dem die JPG-Bilder der Unterverzeichnisse kompressionsfrei in ein Zip-Archiv gepackt werden sollen sodass dieses heruntergeladen werden kann.


PHP:
// Pfad des zu archivierenden Ordners
$folder = "bildarchiv/";
// $folder = dirname( dirname(__FILE__) ). "/subfolder";

// Dateiname Zip-Archiv
$zipfilename = "Bildarchiv_SMLP";
$zipfile = $zipfilename . ".zip";


// Zu ignorierende Dateinamen
// $skip_list = array('php','htaccess','htpasswd','zip','thumb');

// Counter
$fc = 0;            // File-Counter
$dc = 0;            // Directory-Counter


// Entferne Zip-File und etwaige temporäre Dateien aus fehlgeschlagenen Versuchen
$list = glob($zipfilename . "*");
foreach ($list as &$file) {
    unlink($file);
}


// Objekt erstellen und schauen, ob der Server zippen kann
$zip = new ZipArchive();
if ($zip->open($zipfile, ZIPARCHIVE::CREATE) !== TRUE) {        // Überschreibe Datei
    die ("Das Archiv konnte nicht erstellt werden!");
}
/*  
if (file_exists($zipfile)) {                                        // Wenn Zip-Datei bereits existiert
    if ($zip->open($zipfile, ZIPARCHIVE::OVERWRITE) !== TRUE) {        // Überschreibe Datei
        die ("Das bestehende Archiv konnte nicht ueberschrieben werden!");
    }
} else {                                                            // Wenn Zip-Datei noch nicht existiert
    if ($zip->open($zipfile, ZIPARCHIVE::CREATE) !== TRUE) {        // Erstelle Datei
        die ("Das Archiv konnte nicht erstellt werden!");
    }  
}
*/


/*
$res = $zip->open($zipfile, ZIPARCHIVE::CREATE); // OVERWRITE
if ($res === FALSE) {
    die ("Das Archiv konnte nicht erstellt werden! Bitte kontaktieren Sie mich.");
}
*/


// Gehe durch die Ordner und füge alles dem Archiv hinzu
// $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($folder));
$fullpath = getcwd();    // dirname(__DIR__);  // __DIR__
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.'));

foreach ($iterator as $key=>$value) {

    if(!is_dir($key)) { // Wenn es kein Ordner sondern eine Datei ist
    // echo $key . " _ _ _ _Datei wurde übernommen</br>";

    // Version 2 (Eindeutigkeitsprinzip)
    if (strpos($key, '.jpg') !== false) {                                                                // Pruefe, ob eine Bilddatei
        if (strpos($key, 'thumb') === false) {                                                            // Pruefe, ob kein Thumbnail
            // $zip->addFile(realpath($key), $key) or die ("FEHLER: Kann Datei nicht anfuegen: $key");        // Fuege Datei hinzu
            //echo realpath($key) . " hinzugefügt</br>";
            $zip->addFile(realpath($key), substr(str_replace($fullpath,'',$key),2)) or die ("FEHLER: Kann Datei nicht anfuegen: $key");
            $zip->setCompressionIndex($fc, ZipArchive::CM_STORE);                                        // Setze Kompression auf Null
            $fc++;                                                                                        // Erhöhe Zähler
           
            /*
            if (($fc % 50) == 0) {                        // Pruefe, ob i 100ste Datei geschrieben
                echo "happening\n";
                $zip->close();
                $zip = null; //unset($null)
                $zip = new ZipArchive;
                $zip->open($zipfile,ZIPARCHIVE::CREATE); // CREATE identisch zu "weiterschreiben"
            }
            */
        }
    }
   
    /*
    // Version 1 (Ausschlussprinzip)
    $skipfile = false;
    foreach ($skip_list as &$seachword) {
        if (strpos($key, $seachword) !== false) {
            $skipfile = true;
            break;
        }
    }
   
    if (!$skipfile) {
        $zip->addFile(realpath($key), $key) or die ("FEHLER: Kann Datei nicht anfuegen: $key");  
        $fc++;
    }
    */
   
    } elseif (count(scandir($key)) <= 2) { // der ordner ist bis auf . und .. leer
    // echo $key . " _ _ _ _Leerer Ordner wurde uebernommen</br>";
    //$zip->addEmptyDir(substr($key, -1*strlen($key),strlen($key)-1));
    //$dc++;

    } elseif (substr($key, -2)=="/.") { // ordner .
    $dc++; // Ausschliesslich fuer den Abschlussbericht
   
    } elseif (substr($key, -3)=="/.."){ // ordner ..
    // Tue nichts
   
    } else { // Zeige andere ausgelassene Ordner (sollte nicht vorkommen)
    echo $key . "WARNUNG: Der Ordner wurde nicht ins Archiv übernommen.</br>";
    }
}

// Speichert die Zip-Datei
if ($zip->close() !== TRUE) {
    die ("Das Archiv konnte nicht gespeichert werden!");
}

Problem dabei ist nun, dass das Skript jeden Tag von Neuem einige wenige Male fehlschlägt bis es klappt.

Der Verlauf ist beispielsweise wie folgt:
1. Versuch: 60 Sekunden bis Abbruch für ein 300 MB temp-Zip-File
2. Versuch: 60 Sekunden bis Abbruch für ein 600 MB temp-Zip-File
3. Versuch: 60 Sekunden bis Abbruch für ein 950 MB temp-Zip-File
4. Versuch: 60 Sekunden bis Abbruch für ein 1,2 GB temp-Zip-File
5. Versuch: ca. 1-3 Sekunden bis zum Erfolg für ein 1,25 GB Zip-File

Jeder weitere Versuch, zumindest amselben Tag, erstellt das Zip-File dann erneut innerhalb weniger Sekunden. Die unvollendeten temporären Zip-Dateien werden vor jedem neuen Versuch automatisch gelöscht.

Ich verstehe nicht wieso das Skript zu Beginn eines Tages einige Male nicht funktioniert und immer dann wenn es einmal funktioniert hat mit jedem weiteren Versuch funktioniert - selbst wenn ich Dateien austausche.

Irgendwelche Ideen?

PS: Die 60 Sekunden sind natürlich Server-Konfiguration.
 
Völlig ins blaue getippt und irgendwie ne richtig wilde Idee:
Bei den ersten Anläufen liest der Host die Dateien ein, wird aber nicht rechtzeitig fertig. Mit jedem Durchlauf landet mehr und mehr im Cache des Hosts, weshalb das Einlesen schneller geht und irgendwann ist er schnell genug durch. Wird das Skript dann länger nicht genutzt, rutschen die Dateien wieder aus dem Cache und das Spiel geht von vorne los.

Bau dir eine Logausgabe (in eine Datei am besten) ein und lass dir da ausgeben, wie lange es pro Datei dauert, die in das ZIP zu packen.

Nachtrag:
Eigentlich geht es ja hier um einen 504... ist das ZIP denn trotzdem fertig und vollständig nach dem ersten Durchlauf oder wird das auch das PHP Skript nach 60 Sekunden gekillt? Falls das Skript weiterläuft, musst du dir da eventuell was asynchrones ausdenken.
 
Ich hatte eben versucht Dateiname und Zeitdauer per echo oder print Befehl auszugeben aber die Anzeige auf dem Bildschirm erfolgt irgendwie nur dann, wenn das Skript auch erfolgreich ausgeführt werden konnte (obwohl die Befehle in der Schleife stehen).

Das Zip-Archiv ist nach Skript-Abbruch nicht fertig, nur die temporäre Datei verschiedener Größe liegt dann auf dem Webspace.

Aber! ich glaube Du hast Recht mit der Cache, denn:
Die sichtbare Temp-Datei wird zwar vom Skript jedes Mal zu Beginn eines Versuchs entfernt aber als ich nach Beginn eines weiteren Versuchs die Ansicht im FTP-Browser aktualisiert habe war die Datei etwas über 600 MB und kurz zuvor war sie noch (bei Abbruch des letzten Versuchs, und vor dem Löschen) knapp unter 600 MB groß gewesen. Könnte also wirklich so sein.

Aber wenn das so ist, und wir da jetzt mal davon ausgehen - wie kann ich das Problem denn nun lösen? Würde es helfen die Zip-Datei z. B. immer nach 100 Dateien abzuschließen und dann wieder zu erweitern?

Edit: Wenn das so, ist bedeutet das ja, dass die korrekte Ausführung eben weit mehr als 60 Sekunden benötigt - eigentlich eh viel zu lange für eine Dateimenge von 1,2 GB und einer kompressionslosen Speicherung...
 
Zuletzt bearbeitet:
Zurück
Oben