Add multi-file upload that zips files server-side

This commit is contained in:
root
2026-03-23 17:02:26 +01:00
parent a3348e8795
commit 09d919ca27
4 changed files with 268 additions and 16 deletions

View File

@@ -102,7 +102,7 @@
<div id="upload-ui">
<div id="drop-zone" class="drop-zone mb-4">
<input type="file" id="fileInput" class="hidden">
<input type="file" id="fileInput" class="hidden" multiple>
<div id="dz-content">
<span id="dz-text" class="text-sm">Click to select or drop file</span>
@@ -232,20 +232,36 @@
input.onchange = () => {
if (input.files.length) {
showFile(input.files[0]);
showFiles(input.files);
uploadBtn.disabled = false;
} else {
uploadBtn.disabled = true;
}
};
function showFile(file) {
function showFiles(fileList) {
const files = Array.from(fileList || []);
if (files.length === 0) return;
const total = files.reduce((acc, f) => acc + f.size, 0);
if (files.length === 1) {
document.getElementById('dz-text').innerText =
`${files[0].name} (${formatBytes(files[0].size)})`;
return;
}
document.getElementById('dz-text').innerText =
`${file.name} (${formatBytes(file.size)})`;
`${files.length} FILES (${formatBytes(total)}) — will be zipped`;
}
uploadBtn.onclick = () => {
if (input.files.length) handleUpload(input.files[0]);
if (!input.files.length) return;
if (input.files.length === 1) {
handleUploadSingle(input.files[0]);
} else {
handleUploadMulti(input.files);
}
};
cancelBtn.onclick = (e) => {
@@ -257,7 +273,15 @@
}
};
function handleUpload(file) {
function commonFormData() {
const fd = new FormData();
fd.append("once", document.getElementById("once").checked ? "true" : "false");
const hours = parseInt(document.getElementById("duration").value, 10);
fd.append("duration", hours);
return fd;
}
function startUploadUI() {
uploadBtn.disabled = true;
uploadBtn.innerText = "UPLOADING...";
cancelBtn.classList.remove('hidden');
@@ -265,16 +289,9 @@
progressContainer.classList.remove("hidden");
progressText.classList.remove("hidden");
statsText.classList.remove("hidden");
}
const fd = new FormData();
fd.append("file", file);
fd.append("once", document.getElementById("once").checked ? "true" : "false");
const hours = parseInt(document.getElementById("duration").value, 10);
fd.append("duration", hours);
const xhr = new XMLHttpRequest();
currentXhr = xhr;
function setupXHRHandlers(xhr) {
let startTime = Date.now();
xhr.upload.onprogress = (e) => {
@@ -301,7 +318,6 @@
const data = JSON.parse(xhr.responseText);
if (data.error) throw new Error(data.error);
// Redirect using view key
window.location.href = "/f/" + data.view_key;
} catch (err) {
@@ -319,11 +335,38 @@
location.reload();
}
};
}
function handleUploadSingle(file) {
startUploadUI();
const fd = commonFormData();
fd.append("file", file);
const xhr = new XMLHttpRequest();
currentXhr = xhr;
setupXHRHandlers(xhr);
xhr.open("POST", "/api/files/upload");
xhr.send(fd);
}
function handleUploadMulti(fileList) {
startUploadUI();
const fd = commonFormData();
Array.from(fileList).forEach(f => fd.append("files", f));
const xhr = new XMLHttpRequest();
currentXhr = xhr;
setupXHRHandlers(xhr);
xhr.open("POST", "/api/files/upload-multi");
xhr.send(fd);
}
function copy(id) {
const el = document.getElementById(id);
el.select();