From 186b4a27c2a8b1a39e01a9c2ef3779ad5cced85f Mon Sep 17 00:00:00 2001 From: Louis-Alexander Kerst Date: Sat, 22 Aug 2026 10:42:02 +0200 Subject: [PATCH] Zeige Fortschritt bei der WebP-Migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Teilt die Bestandsmigration in einen sicheren Request pro Bild auf, zeigt den tatsächlichen Fortschritt im Adminbereich und erlaubt die Wiederaufnahme nach Gateway- oder Netzwerkabbrüchen. --- README.md | 2 +- admin.php | 203 ++++++++++++++++++++++++++++++++++++++++---------- functions.php | 183 +++++++++++++++++++++++++++++---------------- 3 files changed, 281 insertions(+), 107 deletions(-) diff --git a/README.md b/README.md index 0369ba0..04faebc 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Diese Pfade enthalten den individuellen Datenbestand einer Installation: Beide Bereiche werden von Git ignoriert. Ein normaler `git pull` überschreibt oder löscht sie daher nach der Umstellung nicht. `uploads/.htaccess` und die `.gitignore`-Dateien bleiben Bestandteil des Repositorys. -Erkennt das Admin-Interface vorhandene JPG-/PNG-Bestandsbilder, erscheint automatisch der Hinweis „WebP-Migration verfügbar“. Der dortige Button konvertiert die erkannten Dateien, aktualisiert ihre Verweise in `data/talks.json` und entfernt die Originale erst nach erfolgreicher Datenbankaktualisierung. +Erkennt das Admin-Interface vorhandene JPG-/PNG-Bestandsbilder, erscheint automatisch der Hinweis „WebP-Migration verfügbar“. Der dortige Button konvertiert die erkannten Dateien einzeln, zeigt nach jeder Datei den tatsächlichen Fortschritt an, aktualisiert ihre Verweise in `data/talks.json` und entfernt die Originale erst nach erfolgreicher Datenbankaktualisierung. Eine unterbrochene Migration kann über denselben Button sicher fortgesetzt werden. > **Wichtig:** Auf einem Produktivserver niemals `git clean -fdx` ausführen. Der Parameter `-x` bezieht ignorierte Dateien ein und würde dadurch die JSON-Datenbank und Uploads löschen. diff --git a/admin.php b/admin.php index 1e879ef..838e3af 100644 --- a/admin.php +++ b/admin.php @@ -6,6 +6,14 @@ require_once __DIR__ . '/functions.php'; $loggedIn = isset($_SESSION['admin']) && $_SESSION['admin'] === true; +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['migration_step']) && !$loggedIn) { + header('Content-Type: application/json; charset=utf-8'); + header('Cache-Control: no-store'); + http_response_code(401); + echo json_encode(['ok' => false, 'error' => 'Die Admin-Sitzung ist abgelaufen. Bitte Seite neu laden und anmelden.']); + exit; +} + // Login if (isset($_POST['action']) && $_POST['action'] === 'login') { if (($_POST['password'] ?? '') === ADMIN_PASSWORD_PLAIN) { @@ -30,28 +38,36 @@ if ($loggedIn) { $_SESSION['migration_csrf'] = bin2hex(random_bytes(32)); } $migrationCsrf = (string)$_SESSION['migration_csrf']; - $migrationNotice = $_SESSION['migration_notice'] ?? null; $migrationError = null; - unset($_SESSION['migration_notice']); - // BESTANDS-UPLOADS NACH WEBP MIGRIEREN - if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['migrate_uploads'])) { + // Je Request genau ein Bestandsbild migrieren, damit das Frontend echten + // Fortschritt anzeigen kann und kein langer PHP-Request am Gateway scheitert. + if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['migration_step'])) { + header('Content-Type: application/json; charset=utf-8'); + header('Cache-Control: no-store'); $submittedToken = (string)($_POST['migration_csrf'] ?? ''); if (!hash_equals($migrationCsrf, $submittedToken)) { - $migrationError = 'Die Migrationsanfrage ist abgelaufen. Bitte Seite neu laden und erneut versuchen.'; - } else { - try { - $_SESSION['migration_notice'] = migrate_uploads_to_webp(); - header('Location: admin.php?migration=done'); - exit; - } catch (Throwable $e) { - $migrationError = 'Migration fehlgeschlagen: ' . $e->getMessage(); - } + http_response_code(403); + echo json_encode(['ok' => false, 'error' => 'Die Migrationsanfrage ist abgelaufen. Bitte Seite neu laden.']); + exit; } + + session_write_close(); + try { + $result = migrate_next_upload_to_webp(); + echo json_encode(['ok' => true, 'result' => $result], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR); + } catch (Throwable $e) { + http_response_code(422); + echo json_encode( + ['ok' => false, 'error' => 'Migration fehlgeschlagen: ' . $e->getMessage()], + JSON_UNESCAPED_UNICODE + ); + } + exit; } // CREATE/UPDATE - elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_event'])) { + if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_event'])) { $events = load_events(); $id = $_POST['id'] ?: 'evt_' . bin2hex(random_bytes(6)); $title = sanitize_text($_POST['title'] ?? ''); @@ -226,36 +242,43 @@ if ($loggedIn) { - - - - - - - - -