Fix image uploads and reduce flyer request sizes

This commit is contained in:
kai
2026-08-27 07:34:45 +02:00
parent 41b2c5cd61
commit fd8c216cc8
4 changed files with 96 additions and 5 deletions
+39
View File
@@ -133,6 +133,45 @@
</main>
{% if can_edit_details %}
<script>
const editConcertForm = document.querySelector('form[enctype="multipart/form-data"]');
const editFlyerInput = editConcertForm?.querySelector('input[name="flyer"]');
async function optimizeEditFlyer(file) {
const bitmap = await createImageBitmap(file);
const maxSide = 1800;
const scale = Math.min(1, maxSide / Math.max(bitmap.width, bitmap.height));
const canvas = document.createElement("canvas");
canvas.width = Math.max(1, Math.round(bitmap.width * scale));
canvas.height = Math.max(1, Math.round(bitmap.height * scale));
canvas.getContext("2d").drawImage(bitmap, 0, 0, canvas.width, canvas.height);
bitmap.close();
let quality = 0.86;
let blob;
do {
blob = await new Promise(resolve => canvas.toBlob(resolve, "image/jpeg", quality));
quality -= 0.08;
} while (blob && blob.size > 900 * 1024 && quality >= 0.5);
if (!blob) throw new Error("Bild konnte nicht verarbeitet werden");
return new File([blob], "flyer.jpg", {type: "image/jpeg"});
}
editConcertForm?.addEventListener("submit", async event => {
if (editConcertForm.dataset.flyerOptimized === "true") return;
const file = editFlyerInput?.files[0];
if (!file) return;
event.preventDefault();
try {
const transfer = new DataTransfer();
transfer.items.add(await optimizeEditFlyer(file));
editFlyerInput.files = transfer.files;
editConcertForm.dataset.flyerOptimized = "true";
editConcertForm.requestSubmit();
} catch (error) {
console.error("Flyer optimization failed:", error);
editConcertForm.dataset.flyerOptimized = "true";
editConcertForm.requestSubmit();
}
});
const eventType = document.getElementById("event-type");
const parentEventField = document.getElementById("parent-event-field");
const parentEventId = document.getElementById("parent-event-id");
+42
View File
@@ -877,6 +877,48 @@ flyerInput.addEventListener(
}
);
// Große Flyer vor dem Absenden verkleinern. Dadurch bleibt der Multipart-
// Request unter typischen Proxy-Limits und der Server muss keine riesigen
// Originaldateien verarbeiten.
const concertForm = flyerInput.form;
async function optimizeFlyerUpload(file) {
const bitmap = await createImageBitmap(file);
const maxSide = 1800;
const scale = Math.min(1, maxSide / Math.max(bitmap.width, bitmap.height));
const canvas = document.createElement("canvas");
canvas.width = Math.max(1, Math.round(bitmap.width * scale));
canvas.height = Math.max(1, Math.round(bitmap.height * scale));
const context = canvas.getContext("2d");
context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
bitmap.close();
let quality = 0.86;
let blob;
do {
blob = await new Promise(resolve => canvas.toBlob(resolve, "image/jpeg", quality));
quality -= 0.08;
} while (blob && blob.size > 900 * 1024 && quality >= 0.5);
if (!blob) throw new Error("Bild konnte nicht verarbeitet werden");
return new File([blob], "flyer.jpg", {type: "image/jpeg"});
}
concertForm.addEventListener("submit", async event => {
if (concertForm.dataset.flyerOptimized === "true") return;
const file = flyerInput.files[0];
if (!file) return;
event.preventDefault();
try {
const transfer = new DataTransfer();
transfer.items.add(await optimizeFlyerUpload(file));
flyerInput.files = transfer.files;
concertForm.dataset.flyerOptimized = "true";
concertForm.requestSubmit();
} catch (error) {
console.error("Flyer optimization failed:", error);
concertForm.dataset.flyerOptimized = "true";
concertForm.requestSubmit();
}
});
/* ============================================================
HTML ESCAPING
+2 -2
View File
@@ -213,10 +213,10 @@ if (profileForm) {
context.imageSmoothingQuality = "high";
context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
bitmap.close();
const blob = await new Promise(resolve => canvas.toBlob(resolve, "image/webp", .86));
const blob = await new Promise(resolve => canvas.toBlob(resolve, "image/jpeg", .88));
if (!blob) throw new Error("Bild konnte nicht verarbeitet werden");
const transfer = new DataTransfer();
transfer.items.add(new File([blob], "profilbild.webp", {type: "image/webp"}));
transfer.items.add(new File([blob], "profilbild.jpg", {type: "image/jpeg"}));
input.files = transfer.files;
profileForm.dataset.optimized = "true";
status.textContent = `Optimiert: ${Math.ceil(blob.size / 1024)} KB wird hochgeladen …`;