feat: migrate frame upload to php backend and ntfy
This commit is contained in:
+36
-15
@@ -175,14 +175,7 @@
|
|||||||
<p style="color: var(--text-muted); font-size: 15px;">Lade dein eigenes PNG hoch. Es wird uns per E-Mail gesendet und wir binden es in deine App ein.</p>
|
<p style="color: var(--text-muted); font-size: 15px;">Lade dein eigenes PNG hoch. Es wird uns per E-Mail gesendet und wir binden es in deine App ein.</p>
|
||||||
|
|
||||||
<!-- FormSubmit.co is used to send the email directly with attachment without a backend -->
|
<!-- FormSubmit.co is used to send the email directly with attachment without a backend -->
|
||||||
<!-- The user needs to change the email below -->
|
<form id="bg-upload-form">
|
||||||
<form id="bg-upload-form" action="https://formsubmit.co/jannik.schnappix@gmail.com" method="POST" enctype="multipart/form-data">
|
|
||||||
|
|
||||||
<!-- FormSubmit Configuration -->
|
|
||||||
<input type="hidden" name="_subject" value="Neuer Schnappix Hintergrund Upload!">
|
|
||||||
<input type="hidden" name="_captcha" value="false">
|
|
||||||
<input type="hidden" name="_template" value="table">
|
|
||||||
<!-- Optional: Redirect after success. We use standard submission for now. -->
|
|
||||||
|
|
||||||
<div class="upload-area" id="drop-zone">
|
<div class="upload-area" id="drop-zone">
|
||||||
<i class="fa-solid fa-cloud-arrow-up upload-icon"></i>
|
<i class="fa-solid fa-cloud-arrow-up upload-icon"></i>
|
||||||
@@ -209,10 +202,6 @@
|
|||||||
<button type="submit" class="btn btn-primary btn-block" id="submit-btn">
|
<button type="submit" class="btn btn-primary btn-block" id="submit-btn">
|
||||||
<i class="fa-solid fa-paper-plane" style="margin-right: 8px;"></i> Hintergrund absenden
|
<i class="fa-solid fa-paper-plane" style="margin-right: 8px;"></i> Hintergrund absenden
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<p class="email-info" id="email-info">
|
|
||||||
<i class="fa-solid fa-info-circle"></i> Hinweis für den Webmaster: Ändere die E-Mail-Adresse im <code>action</code>-Attribut des Formulars in der <code>upload.html</code>, um die Dateien an deine eigene Adresse zu senden.
|
|
||||||
</p>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -257,7 +246,6 @@
|
|||||||
const imagePreview = document.getElementById('image-preview');
|
const imagePreview = document.getElementById('image-preview');
|
||||||
const submitBtn = document.getElementById('submit-btn');
|
const submitBtn = document.getElementById('submit-btn');
|
||||||
const customerInfo = document.getElementById('customer-info');
|
const customerInfo = document.getElementById('customer-info');
|
||||||
const emailInfo = document.getElementById('email-info');
|
|
||||||
|
|
||||||
// Drag and Drop Effects
|
// Drag and Drop Effects
|
||||||
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
|
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
|
||||||
@@ -308,7 +296,6 @@
|
|||||||
previewBox.style.display = 'none';
|
previewBox.style.display = 'none';
|
||||||
submitBtn.style.display = 'none';
|
submitBtn.style.display = 'none';
|
||||||
customerInfo.style.display = 'none';
|
customerInfo.style.display = 'none';
|
||||||
emailInfo.style.display = 'none';
|
|
||||||
|
|
||||||
valFormat.innerHTML = `<i class="fa-solid fa-circle-notch fa-spin"></i> Überprüfe Dateiformat...`;
|
valFormat.innerHTML = `<i class="fa-solid fa-circle-notch fa-spin"></i> Überprüfe Dateiformat...`;
|
||||||
valFormat.className = '';
|
valFormat.className = '';
|
||||||
@@ -342,7 +329,6 @@
|
|||||||
previewBox.style.display = 'block';
|
previewBox.style.display = 'block';
|
||||||
customerInfo.style.display = 'block';
|
customerInfo.style.display = 'block';
|
||||||
submitBtn.style.display = 'block';
|
submitBtn.style.display = 'block';
|
||||||
emailInfo.style.display = 'block';
|
|
||||||
} else {
|
} else {
|
||||||
setValidationMsg(valResolution, false, '', `Fehler: Falsche Auflösung (${width}x${height}px). Erwartet: 1500x1000px.`);
|
setValidationMsg(valResolution, false, '', `Fehler: Falsche Auflösung (${width}x${height}px). Erwartet: 1500x1000px.`);
|
||||||
}
|
}
|
||||||
@@ -354,6 +340,41 @@
|
|||||||
};
|
};
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const form = document.getElementById('bg-upload-form');
|
||||||
|
form.addEventListener('submit', async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const formData = new FormData(form);
|
||||||
|
const originalBtnText = submitBtn.innerHTML;
|
||||||
|
submitBtn.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i> Lade hoch...';
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('upload_backend.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
alert('Erfolgreich hochgeladen!');
|
||||||
|
form.reset();
|
||||||
|
previewBox.style.display = 'none';
|
||||||
|
submitBtn.style.display = 'none';
|
||||||
|
customerInfo.style.display = 'none';
|
||||||
|
validationBox.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
alert('Fehler: ' + (result.error || 'Unbekannter Fehler'));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
alert('Upload fehlgeschlagen. Bitte prüfe deine Verbindung.');
|
||||||
|
} finally {
|
||||||
|
submitBtn.innerHTML = originalBtnText;
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
// Check if request is POST
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
http_response_code(405);
|
||||||
|
echo json_encode(['error' => 'Method not allowed']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uploadDir = __DIR__ . '/uploads/';
|
||||||
|
if (!is_dir($uploadDir)) {
|
||||||
|
// Attempt to create if not exists (though Docker should map it)
|
||||||
|
@mkdir($uploadDir, 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if file is uploaded
|
||||||
|
if (!isset($_FILES['background_image']) || $_FILES['background_image']['error'] !== UPLOAD_ERR_OK) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => 'Keine Datei hochgeladen oder Ein Fehler ist aufgetreten.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $_FILES['background_image'];
|
||||||
|
$email = isset($_POST['email']) ? htmlspecialchars($_POST['email']) : 'Keine E-Mail angegeben';
|
||||||
|
|
||||||
|
// Validate file type
|
||||||
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||||
|
$mimeType = finfo_file($finfo, $file['tmp_name']);
|
||||||
|
finfo_close($finfo);
|
||||||
|
|
||||||
|
if ($mimeType !== 'image/png') {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['error' => 'Nur PNG-Dateien sind erlaubt.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate unique filename
|
||||||
|
$filename = uniqid('frame_') . '_' . time() . '.png';
|
||||||
|
$destination = $uploadDir . $filename;
|
||||||
|
|
||||||
|
// Move uploaded file
|
||||||
|
if (move_uploaded_file($file['tmp_name'], $destination)) {
|
||||||
|
// Build public URL
|
||||||
|
// Assuming the app is accessible at https://schnappix.orfel.de
|
||||||
|
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
|
||||||
|
$host = $_SERVER['HTTP_HOST'];
|
||||||
|
$publicUrl = $protocol . '://' . $host . '/uploads/' . $filename;
|
||||||
|
|
||||||
|
// Send notification to Ntfy
|
||||||
|
$ntfyUrl = 'https://ntfy.orfel.de/Schnappix-Frame-Upload';
|
||||||
|
$message = "Ein neuer Rahmen wurde hochgeladen!\n\nVon: $email\nBild-URL: $publicUrl";
|
||||||
|
|
||||||
|
$ch = curl_init($ntfyUrl);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
'Title: Neuer Schnappix Hintergrund',
|
||||||
|
'Tags: frame_with_picture,tada',
|
||||||
|
'Click: ' . $publicUrl,
|
||||||
|
'Attach: ' . $publicUrl
|
||||||
|
]);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
|
||||||
|
curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Datei erfolgreich hochgeladen.',
|
||||||
|
'url' => $publicUrl
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(['error' => 'Fehler beim Speichern der Datei.']);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user