<?php session_start(); require __DIR__ . '/vendor/autoload.php'; use PhotoPrismUpload\API\PhotoPrism; $footer = '<footer style="position: fixed;bottom: 0;left: 0;"><a href="/git/phlaym/photoprismupload">Ich bin Open Source</a></footer>'; ?> <html> <head> <meta charset="UTF-8"> <meta name="color-scheme" content="dark light"> <title>Photoprism Upload</title> <meta name="description" content="Eine Seite um Photos zur Photoprism Instanz hochzuladen"> <meta name="author" content="Max Nuding"> <meta http-equiv="robots" content="noindex,nofollow"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv=”content-language” content=”de-de”/> <style> ::root { background-color: white; color: black; color-scheme: light dark; } @media screen and (prefers-color-scheme: dark) { :root { background-color: rgb(54, 54, 54); color: white; } a { color: rgb(105, 105, 242); } a:visited { color: rgb(152, 95, 215); } } .form-wrapper { display: grid; grid-template-rows: auto auto auto; grid-auto-columns: minmax(auto, 300px) auto; } label[for="album"] { grid-column: 1; grid-row: 1; } #album { grid-column: 2; grid-row: 1; } #input { grid-row: 2; grid-column: 1/3; } .form-wrapper > form:nth-child(1) { display: inherit; } input[type=submit] { grid-column: 2; grid-row: 3; justify-self: right; } #error, #fileProgress, #totalProgress, label[for="fileProgress"], label[for="totalProgress"] { display:none; grid-column: 1; } #uploadForm { grid-row: 1; grid-column: 1; } #error { grid-row: 2; grid-column: 1/3; } label[for="fileProgress"] { grid-row: 3; } #fileProgress { grid-row: 4; width: 100%; } label[for="totalProgress"]{ grid-row: 5; } #totalProgress { grid-row: 6; width: 100%; } footer { margin: 8px; } </style> </head> <body> <?php $config = require(__DIR__ . '/config.php'); $api = new PhotoPrism($config); $albums = []; try { $api->login(); } catch (\Exception $e) { die('Fehler: ' . $e->getMessage().$footer.'</body></html>'); } if (!isset($_POST['submit'])) { if (!isset($_GET['token'])) { die('Sorry, kein Zugriff' . $footer . '</body></html>'); } $token = $_GET['token']; $tokens = explode(',', $token); try { $albums = $api->getAlbumsByTokens($tokens); } catch (\Exception $e) { die('Fehler: ' . $footer . $e->getMessage() . '</body></html>'); } if (empty($albums) && (empty($config['noAlbumToken']) || !in_array($config['noAlbumToken'], $tokens))) { die('Falscher Token' . $footer . '</body></html>'); } ?> <div class="form-wrapper"> <!--<form method="POST" enctype="multipart/form-data" onsubmit="return validateForm();" id="uploadForm"> !--> <form method="POST" enctype="multipart/form-data" id="uploadForm"> <label for="album">Zu Album hinzufügen</label> <select name="album" id="album"> <option value="">---</option> <?php foreach ($albums as $album) { echo '<option value="' . $album->uid . '">' . $album->title . '</option>\n'; } ?> </select> <!--<label></label> <input type="text" />!--> <input multiple type="file" name="files[]" id="input" required/> <input type="submit" name="submit" value="Upload" /> </form> <div id="error"></div> <label for="fileProgress">Datei:</label> <progress id="fileProgress"></progress> <label for="totalProgress">Gesamt:</label> <progress max="0" value="0" id="totalProgress"></progress> </div> <script> window.tooLarge = false; window.tooManyFiles = false; const form = document.getElementById('uploadForm'); const submitButton = form.querySelector('input[type=submit]'); const albumInput = form.querySelector('select[name=album]'); const input = document.getElementById('input'); const fileProgress = document.getElementById('fileProgress'); const totalProgress = document.getElementById('totalProgress'); const fileProgressLabel = document.querySelector('label[for=fileProgress]'); const totalProgressLabel = document.querySelector('label[for=totalProgress]'); const errorDiv = document.getElementById('error'); async function postData(url, data = {}, method = 'POST') { const response = await fetch(url, { method: method, body: data }); return response; } form.addEventListener('submit', async function(event) { event.preventDefault(); const isInvalid = window.tooLarge || window.tooManyFiles; if (isInvalid) { console.error('Aborting upload! Too many fiels or fiels too large'); return; } errorDiv.innerText = ''; fileProgressLabel.style.display = 'inherit'; totalProgressLabel.style.display = 'inherit'; fileProgress.style.display = 'inherit'; totalProgress.style.display = 'inherit'; let idx = 0; for (file of fileList) { console.log('Starting upload', file); fileProgressLabel.innerText = `Datei: ${file.name}` totalProgressLabel.innerText = `Gesamt: ${idx} von ${fileList.length} fertig`; totalProgress.value = idx++; let formData = new FormData(); formData.set(input.name, file); formData.set(submitButton.name, submitButton.value); formData.set(albumInput.name, albumInput.value); try { let resp = await postData(form.action, formData, form.method); } catch(e) { console.error('Error uploading file', e); errorDiv.innerHTML += `Fehler beim Upload der Datei ${file.name}: ${e}<br />`; errorDiv.style.display = 'block'; } } totalProgressLabel.innerText = `Gesamt: ${idx} von ${fileList.length} fertig`; totalProgress.value = idx++; fileProgress.max = 1; fileProgress.value = 1; }); let fileList = []; input.addEventListener('change', (event) => { const maxFileSize = <?=$config['fileUploadLimitMb'];?>; const maxAmountOfFiles = <?=$config['maximumNumberOfFilesPerUpload'];?>; const errorDiv = document.getElementById('error'); const totalProgress = document.getElementById('totalProgress'); errorDiv.innerText = ''; errorDiv.style.display = 'none'; submitButton.disabled = false; const target = event.target; fileList = []; const filesTooLarge = []; if (target.files) { for (file of target.files) { const sizeInMb = file.size / 1024 / 1024; if (sizeInMb >= maxFileSize) { filesTooLarge.push(file.name); console.warn('File', file.name, 'is', sizeInMb, 'MB big, which is over the limit of', maxFileSize); } fileList.push(file); } } totalProgress.max = fileList.length; window.tooManyFiles = fileList.length > maxAmountOfFiles; if (window.tooManyFiles) { errorDiv.style.display = 'block'; errorDiv.innerHTML += `Das sind zu viele Dateien, du darfst max. ${maxAmountOfFiles} Dateien gleichzeitig hochladen. `; submitButton.disabled = true; console.warn('Total files:', target.files.length, '. Too many!'); } window.tooLarge = filesTooLarge.length > 0; if (window.tooLarge) { const names = filesTooLarge.join(', ') errorDiv.style.display = 'block'; const pluralizedMessage = filesTooLarge.length > 1 ? 'Die folgenden Dateien sind' : 'Die folgende Datei ist'; errorDiv.innerHTML += `${pluralizedMessage} zu groß: ${names}. Jede Datei darf max. ${maxFileSize} MB groß sein.`; submitButton.disabled = true; } }); </script> <?php die($footer . '</body></html>'); } try { $api->uploadPhotos($_POST['album']); } catch (\Exception $e) { die('Fehler: ' . $footer . $e->getMessage() .'</body></html>'); } ?> Erfolg! <a href=".">Zurück</a> </body></html>