refactored uploadFiles()
This commit is contained in:
@@ -188,6 +188,17 @@
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function finishUpload(success) {
|
||||||
|
UI.overallProgressContainer.style.display = "none";
|
||||||
|
UI.overallProgress.value = 0;
|
||||||
|
UI.overallStatus.textContent = "";
|
||||||
|
UI.currentFileName.textContent = "";
|
||||||
|
fetchFiles();
|
||||||
|
if (success) {
|
||||||
|
showSuccess("Upload successful");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getUIElements() {
|
function getUIElements() {
|
||||||
UI.currentFileName = document.getElementById("currentFileName");
|
UI.currentFileName = document.getElementById("currentFileName");
|
||||||
UI.dropzone = document.getElementById("dropzone");
|
UI.dropzone = document.getElementById("dropzone");
|
||||||
@@ -219,6 +230,13 @@
|
|||||||
return (bytesPerSec / (1024 * 1024)).toFixed(2) + " MB/s";
|
return (bytesPerSec / (1024 * 1024)).toFixed(2) + " MB/s";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initUIProgress() {
|
||||||
|
UI.overallProgressContainer.style.display = "block";
|
||||||
|
UI.overallProgress.value = 0;
|
||||||
|
UI.overallStatus.textContent = "";
|
||||||
|
UI.currentFileName.textContent = "";
|
||||||
|
}
|
||||||
|
|
||||||
function renderFileList(files) {
|
function renderFileList(files) {
|
||||||
if (!UI.fileList) return;
|
if (!UI.fileList) return;
|
||||||
|
|
||||||
@@ -324,43 +342,23 @@
|
|||||||
const files = Array.from(fileListLike);
|
const files = Array.from(fileListLike);
|
||||||
if (files.length === 0) return;
|
if (files.length === 0) return;
|
||||||
|
|
||||||
for (const f of files) {
|
if (!validateFiles(files)) return;
|
||||||
if (sanitizeFilename(f.name) == ".upload") {
|
|
||||||
showError("Invalid filename: .upload");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sanitizeFilename(f.name) in Files) {
|
|
||||||
showError("File already exists: " + f.name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let noErrorOccurred = true;
|
initUIProgress();
|
||||||
|
|
||||||
UI.overallProgressContainer.style.display = "block";
|
|
||||||
UI.overallProgress.value = 0;
|
|
||||||
UI.overallStatus.textContent = "";
|
|
||||||
UI.currentFileName.textContent = "";
|
|
||||||
|
|
||||||
const totalSize = files.reduce((sum, f) => sum + f.size, 0);
|
const totalSize = files.reduce((sum, f) => sum + f.size, 0);
|
||||||
let uploadedBytes = 0;
|
let uploadedBytes = 0;
|
||||||
const t0 = Date.now();
|
let currentIndex = 0;
|
||||||
let idx = 0;
|
const startTime = Date.now();
|
||||||
|
let allSuccessful = true;
|
||||||
|
|
||||||
const uploadNext = () => {
|
function uploadNext() {
|
||||||
if (idx >= files.length) {
|
if (currentIndex >= files.length) {
|
||||||
UI.overallProgressContainer.style.display = "none";
|
finishUpload(allSuccessful);
|
||||||
UI.overallProgress.value = 0;
|
|
||||||
UI.overallStatus.textContent = "";
|
|
||||||
UI.currentFileName.textContent = "";
|
|
||||||
fetchFiles();
|
|
||||||
if (noErrorOccurred) {
|
|
||||||
showSuccess("Upload successful");
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const file = files[idx];
|
const file = files[currentIndex];
|
||||||
UI.currentFileName.textContent = file.name;
|
UI.currentFileName.textContent = file.name;
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
@@ -368,60 +366,76 @@
|
|||||||
form.append("uploadfile", file);
|
form.append("uploadfile", file);
|
||||||
|
|
||||||
xhr.upload.addEventListener("progress", (e) => {
|
xhr.upload.addEventListener("progress", (e) => {
|
||||||
if (!e.lengthComputable) return;
|
if (e.lengthComputable) {
|
||||||
|
updateProgressUI(uploadedBytes + e.loaded, totalSize, startTime);
|
||||||
const totalUploaded = uploadedBytes + e.loaded;
|
}
|
||||||
const percent = (totalUploaded / totalSize) * 100;
|
|
||||||
UI.overallProgress.value = percent;
|
|
||||||
|
|
||||||
const elapsed = (Date.now() - t0) / 1000;
|
|
||||||
const speed = totalUploaded / elapsed;
|
|
||||||
const speedStr = humanReadableSpeed(speed);
|
|
||||||
|
|
||||||
const remainingBytes = totalSize - totalUploaded;
|
|
||||||
const etaSec = speed > 0 ? remainingBytes / speed : Infinity;
|
|
||||||
const min = Math.floor(etaSec / 60);
|
|
||||||
const sec = Math.floor(etaSec % 60);
|
|
||||||
|
|
||||||
UI.overallStatus.textContent =
|
|
||||||
`${percent.toFixed(1)}% (${(totalSize / 1024 / 1024).toFixed(
|
|
||||||
1
|
|
||||||
)} MB total) — ` +
|
|
||||||
`Speed: ${speedStr}, Est. time left: ${
|
|
||||||
isFinite(etaSec) ? `${min}m ${sec}s` : "calculating…"
|
|
||||||
}`;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
xhr.addEventListener("load", () => {
|
xhr.addEventListener("load", () => {
|
||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
uploadedBytes += file.size;
|
uploadedBytes += file.size;
|
||||||
|
} else if (xhr.status === 409) {
|
||||||
|
showError("File already exists: " + file.name);
|
||||||
|
allSuccessful = false;
|
||||||
} else {
|
} else {
|
||||||
if (xhr.status === 409) {
|
showError("Upload failed: " + file.name);
|
||||||
showError("File already exists: " + file.name);
|
allSuccessful = false;
|
||||||
noErrorOccurred = false;
|
|
||||||
} else {
|
|
||||||
showError("Upload failed: " + file.name);
|
|
||||||
noErrorOccurred = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
idx++;
|
currentIndex++;
|
||||||
uploadNext();
|
uploadNext();
|
||||||
});
|
});
|
||||||
|
|
||||||
xhr.addEventListener("error", () => {
|
xhr.addEventListener("error", () => {
|
||||||
showError("Network or server error during upload.");
|
showError("Network or server error during upload.");
|
||||||
noErrorOccurred = false;
|
allSuccessful = false;
|
||||||
idx++;
|
currentIndex++;
|
||||||
uploadNext();
|
uploadNext();
|
||||||
});
|
});
|
||||||
|
|
||||||
xhr.open("POST", AppConfig.Endpoints.Upload);
|
xhr.open("POST", AppConfig.Endpoints.Upload);
|
||||||
xhr.send(form);
|
xhr.send(form);
|
||||||
};
|
}
|
||||||
|
|
||||||
fetchFiles();
|
fetchFiles();
|
||||||
uploadNext();
|
uploadNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateProgressUI(totalUploaded, totalSize, startTime) {
|
||||||
|
const percent = (totalUploaded / totalSize) * 100;
|
||||||
|
UI.overallProgress.value = percent;
|
||||||
|
|
||||||
|
const elapsed = (Date.now() - startTime) / 1000;
|
||||||
|
const speed = totalUploaded / elapsed;
|
||||||
|
const speedStr = humanReadableSpeed(speed);
|
||||||
|
|
||||||
|
const remainingBytes = totalSize - totalUploaded;
|
||||||
|
const etaSec = speed > 0 ? remainingBytes / speed : Infinity;
|
||||||
|
const min = Math.floor(etaSec / 60);
|
||||||
|
const sec = Math.floor(etaSec % 60);
|
||||||
|
|
||||||
|
UI.overallStatus.textContent =
|
||||||
|
`${percent.toFixed(1)}% (${(totalSize / 1024 / 1024).toFixed(
|
||||||
|
1
|
||||||
|
)} MB total) — ` +
|
||||||
|
`Speed: ${speedStr}, Est. time left: ${
|
||||||
|
isFinite(etaSec) ? `${min}m ${sec}s` : "calculating…"
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateFiles(files) {
|
||||||
|
for (const f of files) {
|
||||||
|
const safeName = sanitizeFilename(f.name);
|
||||||
|
if (safeName === ".upload") {
|
||||||
|
showError("Invalid filename: .upload");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (safeName in Files) {
|
||||||
|
showError("File already exists: " + f.name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", initApp);
|
document.addEventListener("DOMContentLoaded", initApp);
|
||||||
})();
|
})();
|
||||||
|
Reference in New Issue
Block a user