|
@@ -119,14 +119,73 @@ export default class OSSSerive {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-export const client = new OSS({
|
|
|
|
|
- region: "oss-cn-hangzhou", // oss地址
|
|
|
|
|
- accessKeyId: "LTAI5tKa6kzGr5EyPWJB4EcD", // 通过阿里云控制台创建的AccessKey ID。
|
|
|
|
|
- accessKeySecret: "arHxB7ZPhizrBYf4844TtyaRctPMgW", // 通过阿里云控制台创建的AccessKey Secret。
|
|
|
|
|
- bucket: import.meta.env.VITE_OSS_BUCKET, // 仓库名字:由 .env 决定(dev=xgxm-test / build=xg-pg),勿在此硬编码切换
|
|
|
|
|
- useFetch: true, // 支持上传大于100KB的文件
|
|
|
|
|
- secure: false, // 返回的url为https
|
|
|
|
|
-});
|
|
|
|
|
|
|
+// OSS 客户端改用 STS 临时凭证:不再硬编码永久 AccessKey。
|
|
|
|
|
+// 上传前向后端 /oss/oss/getAccess 换取限时凭证,缓存复用;
|
|
|
|
|
+// 大文件分片上传期间由 SDK 的 refreshSTSToken 按间隔自动续期,避免临期上传中断。
|
|
|
|
|
+
|
|
|
|
|
+// 换取并校验 STS 临时凭证(status=200 且凭证非空才返回)
|
|
|
|
|
+async function fetchStsToken() {
|
|
|
|
|
+ const res = await request({
|
|
|
|
|
+ url: prefix + "/oss/oss/getAccess",
|
|
|
|
|
+ method: "post",
|
|
|
|
|
+ });
|
|
|
|
|
+ if (
|
|
|
|
|
+ !res ||
|
|
|
|
|
+ String(res.status) !== "200" ||
|
|
|
|
|
+ !res.AccessKeyId ||
|
|
|
|
|
+ !res.SecurityToken
|
|
|
|
|
+ ) {
|
|
|
|
|
+ throw new Error(
|
|
|
|
|
+ "获取OSS临时凭证失败" +
|
|
|
|
|
+ (res && res.status ? "(status=" + res.status + ")" : "")
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ return res;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+let ossClientCache = null; // { client, expireAt }
|
|
|
|
|
+let ossClientPending = null; // 并发上传时共用一次凭证请求,避免重复换取
|
|
|
|
|
+
|
|
|
|
|
+async function getOssClient() {
|
|
|
|
|
+ const now = Date.now();
|
|
|
|
|
+ // 凭证提前 5 分钟刷新,避免拿到临期凭证
|
|
|
|
|
+ if (ossClientCache && now < ossClientCache.expireAt - 5 * 60 * 1000) {
|
|
|
|
|
+ return ossClientCache.client;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!ossClientPending) {
|
|
|
|
|
+ ossClientPending = fetchStsToken()
|
|
|
|
|
+ .then((res) => {
|
|
|
|
|
+ const expireAt = res.Expiration
|
|
|
|
|
+ ? new Date(res.Expiration).getTime()
|
|
|
|
|
+ : Date.now() + 60 * 60 * 1000;
|
|
|
|
|
+ const ossClient = new OSS({
|
|
|
|
|
+ region: "oss-cn-hangzhou", // oss地址
|
|
|
|
|
+ accessKeyId: res.AccessKeyId, // STS 临时 AccessKeyId
|
|
|
|
|
+ accessKeySecret: res.AccessKeySecret, // STS 临时 AccessKeySecret
|
|
|
|
|
+ stsToken: res.SecurityToken, // STS 安全令牌,临时凭证必带
|
|
|
|
|
+ bucket: res.Bucket || import.meta.env.VITE_OSS_BUCKET, // 优先后端返回的桶(随环境),兜底 .env
|
|
|
|
|
+ useFetch: true, // 支持上传大于100KB的文件
|
|
|
|
|
+ secure: false, // 与原有行为保持一致
|
|
|
|
|
+ // 每个请求前 SDK 按间隔自动续期凭证,保障超大文件长时间分片上传不中断
|
|
|
|
|
+ refreshSTSToken: async () => {
|
|
|
|
|
+ const r = await fetchStsToken();
|
|
|
|
|
+ return {
|
|
|
|
|
+ accessKeyId: r.AccessKeyId,
|
|
|
|
|
+ accessKeySecret: r.AccessKeySecret,
|
|
|
|
|
+ stsToken: r.SecurityToken,
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ refreshSTSTokenInterval: 5 * 60 * 1000, // 续期间隔 5 分钟,远小于凭证 1 小时有效期
|
|
|
|
|
+ });
|
|
|
|
|
+ ossClientCache = { client: ossClient, expireAt };
|
|
|
|
|
+ return ossClient;
|
|
|
|
|
+ })
|
|
|
|
|
+ .finally(() => {
|
|
|
|
|
+ ossClientPending = null;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ return ossClientPending;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
export const headers = {
|
|
export const headers = {
|
|
|
// 指定该Object被下载时网页的缓存行为。
|
|
// 指定该Object被下载时网页的缓存行为。
|
|
@@ -286,6 +345,16 @@ export async function httpRequest(file, name, type, maxValue) {
|
|
|
const fileName = filePath + name + "." + exname;
|
|
const fileName = filePath + name + "." + exname;
|
|
|
// console.log(fileName, '文件名')
|
|
// console.log(fileName, '文件名')
|
|
|
|
|
|
|
|
|
|
+ // 获取 OSS 临时凭证客户端(STS,过期自动刷新);失败按上传失败处理
|
|
|
|
|
+ let client;
|
|
|
|
|
+ try {
|
|
|
|
|
+ client = await getOssClient();
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ console.log("上传失败", err);
|
|
|
|
|
+ file.onError("上传失败");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
await client
|
|
await client
|
|
|
.multipartUpload(fileName, file.file, {
|
|
.multipartUpload(fileName, file.file, {
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
// eslint-disable-next-line no-unused-vars
|