From 0648032e84494cefd040bfbd0a22f6114e8a66a3 Mon Sep 17 00:00:00 2001 From: TongTongStudio Date: Sun, 9 Aug 2026 12:34:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(upload-package):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=89=8D=E6=96=87=E4=BB=B6=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=EF=BC=8C=E9=81=BF=E5=85=8D=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E8=A2=AB=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在下载安装包前增加 HEAD 请求校验,确认资源存在且为正确的文件类型, 防止后端错误页(如 f.txt)被当作安装包下载。若 HEAD 因 CORS 限制失败, 则回退为直接下载,避免误报。 --- .env.development | 2 +- pnpm-workspace.yaml | 3 ++ .../app-manager/upload-package/index.vue | 30 +++++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 pnpm-workspace.yaml diff --git a/.env.development b/.env.development index b4d8f138..fa63ee85 100644 --- a/.env.development +++ b/.env.development @@ -8,7 +8,7 @@ VITE_APP_BASE_API=/dev-api # 接口地址 # VITE_APP_API_URL=https://api.youlai.tech # 线上 # VITE_APP_API_URL=https://api.youlai.tech/v2 # 线上(多租户) -VITE_APP_API_URL=http://192.168.5.224:8000 # 本地 +VITE_APP_API_URL=http://127.0.0.1:8000 # 本地 # 启用 Mock 服务(true:开启 false:关闭) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 00000000..4ed7ff6f --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +allowBuilds: + '@parcel/watcher': true + es5-ext: true diff --git a/src/views/app-manager/upload-package/index.vue b/src/views/app-manager/upload-package/index.vue index 119d19a4..70dddd97 100644 --- a/src/views/app-manager/upload-package/index.vue +++ b/src/views/app-manager/upload-package/index.vue @@ -341,15 +341,39 @@ function openDetail(item: AppPackage) { detailVisible.value = true; } -function download(item: AppPackage) { +async function download(item: AppPackage) { if (!item.fileUrl) { ElMessage.warning("文件地址缺失"); return; } + + const url = withBase(item.fileUrl); + const fileName = item.originalName || `${item.packageName}.${item.packageType}`; + + // 先校验资源是否真实存在,避免后端返回的错误页(如 f.txt)被当作文件下载。 + // 受 CORS 限制时 HEAD 可能失败,此时回退为直接下载( 下载不受 CORS 限制),避免误报。 + try { + const resp = await fetch(url, { method: "HEAD" }); + if (!resp.ok) { + ElMessage.error(`下载失败:资源不存在(${resp.status})`); + return; + } + const contentType = resp.headers.get("Content-Type") || ""; + // 资源存在但返回的是文本/HTML/JSON 错误页,而不是实际安装包 + if (/(text\/html|text\/plain|application\/json)/i.test(contentType)) { + ElMessage.error("下载失败:资源未找到或链接无效"); + return; + } + } catch { + // HEAD 不可达(多为跨域限制),直接走原生下载兜底 + } + const a = document.createElement("a"); - a.href = withBase(item.fileUrl); - a.download = item.originalName || `${item.packageName}.${item.packageType}`; + a.href = url; + a.download = fileName; + document.body.appendChild(a); a.click(); + document.body.removeChild(a); } async function handleDelete(item: AppPackage) {