From 1663d9909d65f481c73c4004245cbe2828b124b2 Mon Sep 17 00:00:00 2001
From: alan <67932758+alan16742@users.noreply.github.com>
Date: Thu, 19 Sep 2024 08:38:42 +0800
Subject: [PATCH] upload large file
---
front-end/index.html | 129 +++++++++++++++++++++++++++++++------------
1 file changed, 94 insertions(+), 35 deletions(-)
diff --git a/front-end/index.html b/front-end/index.html
index 6ada1ee7..a7fba03d 100644
--- a/front-end/index.html
+++ b/front-end/index.html
@@ -1236,10 +1236,10 @@
upload.innerHTML = "";
upload.innerHTML += `
`;
@@ -1563,6 +1563,7 @@
}
const paginatedUpFileList = paginate(upFileList, pageSize);
+
function sendPage(pageIndex = 0) {
if (pageIndex >= paginatedUpFileList.length) {
return;
@@ -1590,48 +1591,106 @@
}
sendPage(0);
- function uploadFileWithProgress(file, uploadUrl) {
- const xhr = new XMLHttpRequest();
+ async function uploadFileWithProgress(file, uploadUrl) {
+ const chunkSize = 1024 * 1024 * 10;
+ const fileSize = file.size;
+ let uploadedBytes = 0;
+ let start = 0;
const progressDiv = document.getElementById("uploadDiv");
-
+ const progressText = document.createElement("div");
const progressContainer = document.createElement("div");
- progressContainer.className = "progress-container";
progressDiv.appendChild(progressContainer);
-
- const progressText = document.createElement("div");
- progressText.className = "progress-text";
progressContainer.appendChild(progressText);
- xhr.upload.onprogress = function (event) {
- if (event.lengthComputable) {
- const percentComplete = Math.round(
- (event.loaded / event.total) * 100
- );
- const progressBar =
- "[" +
- "=".repeat(percentComplete / 5) +
- " ".repeat(20 - percentComplete / 5) +
- "]";
- progressText.textContent = `${file.name}: ${progressBar} ${percentComplete}%`;
+ while (start < fileSize) {
+ try {
+ await uploadChunk(start);
+ start = Math.min(start + chunkSize, fileSize);
+ } catch (error) {
+ if (!(await handleUploadError(error))) {
+ progressText.innerHTML += " Upload failed!";
+ return;
+ }
}
- };
+ }
- xhr.onload = function () {
- if (xhr.status === 200 || 201) {
- progressText.textContent += " Upload complete!";
- } else {
- progressText.innerHTML += " Upload failed!";
- }
- };
+ progressText.innerHTML += " Upload completed!";
- xhr.onerror = function () {
- progressText.innerHTML +=
- " An error occurred during the upload.";
- };
+ async function uploadChunk(start) {
+ const xhr = new XMLHttpRequest();
+ const end = Math.min(start + chunkSize, fileSize);
+ const chunk = file.slice(start, end);
+
+ xhr.open("PUT", uploadUrl);
+ xhr.setRequestHeader(
+ "Content-Range",
+ `bytes ${start}-${end - 1}/${fileSize}`
+ );
+
+ return new Promise((resolve, reject) => {
+ xhr.onloadend = () => {
+ if (xhr.status >= 200 && xhr.status < 300) {
+ uploadedBytes = end;
+ updateTotalProgress();
+ resolve(xhr.status);
+ } else {
+ reject(xhr.status);
+ }
+ };
- xhr.open("PUT", uploadUrl);
- xhr.send(file);
+ xhr.upload.onprogress = (event) => {
+ if (event.lengthComputable) {
+ uploadedBytes = start + event.loaded;
+ updateTotalProgress();
+ }
+ };
+
+ xhr.send(chunk);
+ });
+ }
+
+ async function handleUploadError(error) {
+ let retryCount = 10,
+ delayTime = 1;
+ while (retryCount > 0) {
+ retryCount--;
+ if (error === 416) {
+ await new Promise((resolve) =>
+ sendRequest("GET", uploadUrl, null, null, (data) => {
+ start = parseInt(
+ JSON.parse(data).nextExpectedRanges[0].split("-")[0]
+ );
+ resolve();
+ })
+ );
+ return true;
+ } else {
+ await new Promise((resolve) =>
+ setTimeout(resolve, Math.min((delayTime *= 2) * 1000, 32000))
+ );
+ try {
+ await uploadChunk(start);
+ return true;
+ } catch (err) {
+ error = err;
+ }
+ }
+ }
+ return false;
+ }
+
+ function updateTotalProgress() {
+ const percentComplete = Math.round(
+ (uploadedBytes / fileSize) * 100
+ );
+ const progressBar =
+ "[" +
+ "=".repeat(percentComplete / 5) +
+ " ".repeat(20 - percentComplete / 5) +
+ "]";
+ progressText.textContent = `${file.name}: ${progressBar} ${percentComplete}%`;
+ }
}
}