This commit is contained in:
oneao committed 2026-03-26 17:25:23 +08:00
1 parent c7240ea7c9
commit 189a085353
26 files changed
+2650 -201

No files matched your search

+135 -71
View File
@@ -203,14 +203,113 @@ export function getFileExtension(fileName) {
return fileExt;
}
// 上传到阿里云
// blob fileName fileSize xh moduleid father cateid
export function downloadZip(files, fileName = "文件合集", callback) {
const zip = new JSZip();
const addedFiles = new Set();
const tasks = files.map((item) => {
return getAliyunFileBlob(item.mx_mapfilename)
.then((res) => {
const uniqueFileName = getUniqueFileName(item.mx_filename, addedFiles);
zip.file(uniqueFileName, res, { binary: true });
addedFiles.add(uniqueFileName);
})
.catch((err) => {
// 捕获单个文件下载失败的错误,不影响其他文件下载
console.error(`Failed to download file: ${item.mx_filename}`, err);
});
});
// 关键:使用 Promise.all 确保所有任务完成
return Promise.all(tasks)
.then(() => zip.generateAsync({ type: "blob" }))
.then((res) => {
saveAs(res, `${fileName}.zip`);
callback && callback();
})
.catch((err) => {
callback && callback();
throw err;
});
}
// 处理文件名重复的函数
function getUniqueFileName(fileName, addedFiles) {
let uniqueFileName = fileName;
let counter = 1;
// 如果文件名已经存在,则在文件名后加上 (1), (2), ...
while (addedFiles.has(uniqueFileName)) {
const fileNameWithoutExtension = uniqueFileName.replace(/\.[^/.]+$/, "");
const extension = uniqueFileName.slice(uniqueFileName.lastIndexOf("."));
uniqueFileName = `${fileNameWithoutExtension} (${counter})${extension}`;
counter++;
}
return uniqueFileName;
}
// ============================================ 阿里云上传和下载 ============================================
let cachedCredentials = null; // 用来缓存凭证
let isFetchingCredentials = false; // 控制是否正在请求凭证
// 获取阿里云文件的上传凭证
export function getAliyunUploadCredentials() {
return new Promise((resolve, reject) => {
// 如果缓存中有有效的凭证,则直接使用
if (cachedCredentials && !isCredentialsExpired(cachedCredentials)) {
resolve(cachedCredentials); // 凭证未过期,直接返回缓存的凭证
} else {
// 如果正在请求凭证,则等待
if (isFetchingCredentials) {
const interval = setInterval(() => {
// 等待直到凭证被请求完毕
if (!isFetchingCredentials) {
clearInterval(interval); // 请求完成后停止轮询
resolve(cachedCredentials); // 返回缓存的凭证
}
}, 100); // 每100ms检查一次
} else {
// 如果凭证过期,重新请求新的凭证
isFetchingCredentials = true; // 设置为正在请求凭证状态
getAliyunKeyApi()
.then((res) => {
if (res.success) {
const { accessid, policy, signature, expire, dir, host } = res.data;
// 缓存凭证,并记录过期时间
cachedCredentials = {
accessid,
policy,
signature,
expire: parseInt(expire, 10),
dir,
host,
};
isFetchingCredentials = false; // 请求完成,解除锁定
resolve(cachedCredentials); // 返回新凭证
} else {
isFetchingCredentials = false; // 请求失败,解除锁定
reject(new Error("获取凭证失败"));
}
})
.catch((err) => {
isFetchingCredentials = false; // 请求失败,解除锁定
reject(new Error("请求凭证失败:" + err.message));
});
}
}
});
}
// 上传文件到阿里云
export function uploadFile(blob, fileName, fileExt, fileSize, xh, moduleid, father, cateid) {
return new Promise((resolve, reject) => {
getAliyunKeyApi()
.then(async (res) => {
getAliyunUploadCredentials()
.then(async (aliyunKey) => {
try {
const aliyunKey = res.data;
const formData = new FormData();
let uniqueName = `${Date.now()}_${Math.random().toString(36).slice(2)}`;
@@ -219,12 +318,17 @@ export function uploadFile(blob, fileName, fileExt, fileSize, xh, moduleid, fath
uniqueName += `.${fileExt}`;
}
// 构造上传的文件路径
formData.append("key", `${aliyunKey.dir}${uniqueName}`);
formData.append("OSSAccessKeyId", aliyunKey.accessid);
formData.append("policy", aliyunKey.policy);
formData.append("Signature", aliyunKey.signature);
formData.append("file", blob, uniqueName);
console.log(formData);
console.log(aliyunKey.host);
console.log(aliyunKey.dir);
const xhr = new XMLHttpRequest();
xhr.open("POST", aliyunKey.host, true);
@@ -232,6 +336,7 @@ export function uploadFile(blob, fileName, fileExt, fileSize, xh, moduleid, fath
if (xhr.status === 200 || xhr.status === 204) {
const allFilePath = `${aliyunKey.host}/${aliyunKey.dir}${uniqueName}`;
// 上传后处理(插入文件记录等)
const insertRes = await insertFileApi({
father,
mx_moduleid: moduleid,
@@ -278,76 +383,35 @@ export function uploadFile(blob, fileName, fileExt, fileSize, xh, moduleid, fath
});
}
// 检查凭证是否过期
function isCredentialsExpired(credentials) {
const currentTime = Math.floor(Date.now() / 1000);
return currentTime > credentials.expire;
}
// 获取阿里云文件的 Blob 数据(用于下载)
export function getAliyunFileBlob(url) {
return new Promise((resolve, reject) => {
// 创建一个独立的异步函数来处理 fetch 请求
async function fetchFile() {
try {
const response = await fetch(url, { mode: "cors" });
getAliyunUploadCredentials()
.then((aliyunKey) => {
const downloadUrl = `${url}?OSSAccessKeyId=${aliyunKey.accessid}&policy=${aliyunKey.policy}&Signature=${aliyunKey.signature}`;
// 检查响应状态
if (!response.ok) {
reject(new Error(`下载失败:${response.status}`));
return;
}
// 获取文件内容
const blob = await response.blob();
// 返回blob
resolve(blob);
} catch (error) {
reject(error);
}
}
// 调用异步函数
fetchFile();
});
}
export function downloadZip(files, fileName = "文件合集", callback) {
const zip = new JSZip();
const addedFiles = new Set();
const tasks = files.map((item) => {
return getAliyunFileBlob(item.mx_mapfilename)
.then((res) => {
const uniqueFileName = getUniqueFileName(item.mx_filename, addedFiles);
zip.file(uniqueFileName, res, { binary: true });
addedFiles.add(uniqueFileName);
fetch(downloadUrl, { mode: "cors" })
.then((response) => {
if (!response.ok) {
throw new Error(`下载失败,状态码:${response.status}`);
}
return response.blob();
})
.then((blob) => {
resolve(blob);
})
.catch((error) => {
reject(error);
});
})
.catch((err) => {
// 捕获单个文件下载失败的错误,不影响其他文件下载
console.error(`Failed to download file: ${item.mx_filename}`, err);
});
.catch(reject);
});
// 关键:使用 Promise.all 确保所有任务完成
return Promise.all(tasks)
.then(() => zip.generateAsync({ type: "blob" }))
.then((res) => {
saveAs(res, `${fileName}.zip`);
callback && callback();
})
.catch((err) => {
callback && callback();
throw err;
});
}
// 处理文件名重复的函数
function getUniqueFileName(fileName, addedFiles) {
let uniqueFileName = fileName;
let counter = 1;
// 如果文件名已经存在,则在文件名后加上 (1), (2), ...
while (addedFiles.has(uniqueFileName)) {
const fileNameWithoutExtension = uniqueFileName.replace(/\.[^/.]+$/, "");
const extension = uniqueFileName.slice(uniqueFileName.lastIndexOf("."));
uniqueFileName = `${fileNameWithoutExtension} (${counter})${extension}`;
counter++;
}
return uniqueFileName;
}
// ============================================ 阿里云上传和下载 ============================================