+
- 上传文件到 MinIO/S3
+可拖拽或点击选择,支持多文件上传
+
+
+
+
+
+
+
+
+
+ * 如 bucket 不存在请先在 MinIO 控制台创建
+
+
+
拖拽文件到此上传,或点击选择文件
+
+
-
-
+
diff --git a/scripts/uploader.js b/scripts/uploader.js
index 8dd796c..7eed372 100644
--- a/scripts/uploader.js
+++ b/scripts/uploader.js
@@ -4,6 +4,7 @@ const fileElem = document.getElementById("fileElem");
const uploadList = document.getElementById("uploadList");
const folderNameInput = document.getElementById("folderName");
const bucketNameInput = document.getElementById("bucketName");
+const jsonResult = document.getElementById("jsonResult");
const API_UPLOAD = "http://app.wisdompulse.cn/api/v1/doc/upload-files";
@@ -45,22 +46,6 @@ function createProgressItem(filename) {
return wrapper;
}
-async function handleFiles(files) {
- uploadList.innerHTML = "";
- const bucket = getBucketName();
- if (!bucket) {
- showMsg("请输入 Bucket 名称", false);
- return;
- }
- if (!files || !files.length) return;
- const folder = getTargetFolder();
-
- // 多文件逐个上传,每个单独显示进度
- for (const file of files) {
- await uploadSingleFile(file, bucket, folder);
- }
-}
-
function showMsg(msg, ok) {
const div = document.createElement("div");
div.className = ok ? "success" : "error";
@@ -68,62 +53,137 @@ function showMsg(msg, ok) {
uploadList.appendChild(div);
}
-// 单文件上传,带进度条
-function uploadSingleFile(file, bucket, folder) {
- return new Promise((resolve) => {
- const form = new FormData();
- form.append("bucket", bucket);
- form.append("files", file, file.name);
+// 批量上传(单次FormData),统一进度条管理,JSON右侧展示
+function handleFiles(fileList) {
+ uploadList.innerHTML = "";
+ jsonResult.textContent = "{}";
+ const bucket = getBucketName();
+ if (!bucket) {
+ showMsg("请输入 Bucket 名称", false);
+ return;
+ }
+ if (!fileList || !fileList.length) return;
+ const folder = getTargetFolder();
- const progressItem = createProgressItem(file.name);
- const progressBar = progressItem.querySelector("progress");
- const percentLabel = progressItem.querySelector(".percent-label");
- const msgSpan = progressItem.querySelector(".upload-msg");
+ // 显示所有文件的进度条
+ const fileArr = Array.from(fileList);
+ const progressItems = {};
+ fileArr.forEach(f => {
+ progressItems[f.name] = createProgressItem(f.name);
+ });
- const xhr = new XMLHttpRequest();
- xhr.open("POST", API_UPLOAD);
+ // 构造FormData,支持批量
+ const form = new FormData();
+ form.append("bucket", bucket);
+ if (folder) form.append("folder", folder);
+ fileArr.forEach(f => form.append("files", f, f.name));
- xhr.upload.onprogress = function (e) {
- if (e.lengthComputable) {
- const percent = Math.round((e.loaded / e.total) * 100);
- progressBar.value = percent;
- percentLabel.textContent = percent + "%";
- }
- };
+ // 单一xhr,汇总进度
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", API_UPLOAD);
- xhr.onload = function () {
- progressBar.value = 100;
- percentLabel.textContent = "100%";
- if (xhr.status === 200) {
- try {
- const res = JSON.parse(xhr.responseText);
- // 查找本文件上传结果
- let link = "";
- if (res.files && res.files[file.name]) {
- link = `${file.name} 上传成功`;
- msgSpan.innerHTML = link;
- msgSpan.className = "success";
+ xhr.upload.onprogress = function (e) {
+ if (e.lengthComputable) {
+ // 进度只到99%,收到响应才到100%
+ let percent = Math.round((e.loaded / e.total) * 98); // 98留点余量
+ percent = Math.min(percent, 98);
+ fileArr.forEach(f => {
+ const pi = progressItems[f.name];
+ pi.querySelector("progress").value = percent;
+ pi.querySelector(".percent-label").textContent = percent + "%";
+ });
+ }
+ };
+
+ // 新增处理中提示
+ xhr.upload.onload = function () {
+ fileArr.forEach(f => {
+ const pi = progressItems[f.name];
+ pi.querySelector("progress").value = 99;
+ pi.querySelector(".percent-label").textContent = "99%";
+ const msgSpan = pi.querySelector(".upload-msg");
+ msgSpan.innerHTML = "服务器处理中...";
+ });
+ };
+
+ xhr.onload = function () {
+ fileArr.forEach(f => {
+ const pi = progressItems[f.name];
+ pi.querySelector("progress").value = 100;
+ pi.querySelector(".percent-label").textContent = "100%";
+ });
+
+ // 成功
+ if (xhr.status === 200) {
+ try {
+ const res = JSON.parse(xhr.responseText);
+ jsonResult.textContent = JSON.stringify(res.files, null, 2);
+ fileArr.forEach(f => {
+ const pi = progressItems[f.name];
+ const msgSpan = pi.querySelector(".upload-msg");
+ if (res.files && res.files[f.name]) {
+ msgSpan.innerHTML = `${f.name} 上传成功`;
+ msgSpan.className = "success upload-msg";
} else {
msgSpan.innerHTML = "上传成功";
- msgSpan.className = "success";
+ msgSpan.className = "success upload-msg";
}
- } catch (e) {
- msgSpan.innerHTML = "上传成功";
- msgSpan.className = "success";
- }
- } else {
- msgSpan.innerHTML = "上传失败 " + xhr.status;
- msgSpan.className = "error";
+ });
+ } catch (e) {
+ jsonResult.textContent = "{}";
+ fileArr.forEach(f => {
+ const pi = progressItems[f.name];
+ pi.querySelector(".upload-msg").innerHTML = "上传成功";
+ pi.querySelector(".upload-msg").className = "success upload-msg";
+ });
}
- resolve();
- };
+ }
+ // Nginx/gateway 504/502等超时(后端可能还在处理)
+ else if (xhr.status === 504 || xhr.status === 502) {
+ jsonResult.textContent = "{}";
+ fileArr.forEach(f => {
+ const pi = progressItems[f.name];
+ const msgSpan = pi.querySelector(".upload-msg");
+ msgSpan.innerHTML = "服务器处理中,请稍后在目标目录查看上传结果";
+ msgSpan.className = "success upload-msg";
+ });
+ }
+ // 其它错误
+ else {
+ jsonResult.textContent = "{}";
+ fileArr.forEach(f => {
+ const pi = progressItems[f.name];
+ const msgSpan = pi.querySelector(".upload-msg");
+ msgSpan.innerHTML = "上传失败 " + xhr.status;
+ msgSpan.className = "error upload-msg";
+ });
+ }
+ };
- xhr.onerror = function () {
- msgSpan.innerHTML = "上传异常";
- msgSpan.className = "error";
- resolve();
- };
+ xhr.onerror = function () {
+ fileArr.forEach(f => {
+ const pi = progressItems[f.name];
+ pi.querySelector(".upload-msg").innerHTML = "上传异常";
+ pi.querySelector(".upload-msg").className = "error upload-msg";
+ });
+ jsonResult.textContent = "{}";
+ };
+
+ xhr.send(form);
- xhr.send(form);
- });
}
+
+// === 放在文件结尾,而不是 handleFiles 内部 ===
+const bucketTip = document.getElementById("bucketTip");
+bucketNameInput.addEventListener("change", function () {
+ if (bucketNameInput.value === "kbase-priv") {
+ bucketTip.innerHTML = "私有 bucket 中,文件的可访问链接有效期为 7天";
+ bucketTip.style.color = "#ec0924";
+ } else {
+ bucketTip.innerHTML = "";
+ bucketTip.style.color = "";
+ }
+});
+// 页面加载时自动触发一次
+bucketNameInput.dispatchEvent(new Event("change"));
+
+
- 上传结果 JSON
+{}
* 如 bucket 不存在请先在 MinIO 控制台创建
-
-
-
拖拽文件到此上传,或点击选择文件
-
-
-