From 9d5fe80fb396ffbfbddebee0510143d6fa48620f Mon Sep 17 00:00:00 2001 From: wanghanlin <1533525126@qq.com> Date: Mon, 31 Aug 2026 17:48:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(upload):=20=E4=BF=AE=E5=A4=8D=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E4=B8=8A=E4=BC=A0=E5=A4=9A=E6=96=87=E4=BB=B6=E5=A4=B1?= =?UTF-8?q?=E6=95=88=E4=B8=8E=20401=20=E8=B7=B3=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 上传改走 axios 复用 401 自动刷新,显式 multipart/form-data 修复 MultipartException - DocUpload 文件 Tab 加 multiple,上传 handler 按 TDesign requestMethod 契约重写 - AuthController 的 refresh cookie Secure 属性按请求 scheme 动态判断,HTTP 自动降级 - application.yml / application-dev.yml 统一 refresh-cookie-secure 配置 --- frontend/src/api/upload.ts | 34 +++++------ frontend/src/views/DocUpload.vue | 58 ++++++++++--------- .../wok/supportbot/auth/AuthController.java | 23 +++++--- src/main/resources/application-dev.yml | 3 +- src/main/resources/application.yml | 2 +- 5 files changed, 65 insertions(+), 55 deletions(-) diff --git a/frontend/src/api/upload.ts b/frontend/src/api/upload.ts index 52598a4..1add1dc 100644 --- a/frontend/src/api/upload.ts +++ b/frontend/src/api/upload.ts @@ -1,26 +1,22 @@ -import { getToken } from '@/utils/token' +import request from './request' import type { ApiResponse } from '@/types/api' -/** XMLHttpRequest 上传(带进度回调)—— 保留旧版 api.js 的核心实现 */ -function postFormWithProgress(path: string, formData: FormData, onProgress?: (pct: number) => void): Promise { - return new Promise((resolve, reject) => { - const xhr = new XMLHttpRequest() - xhr.open('POST', path) - const token = getToken() - if (token) xhr.setRequestHeader('Authorization', 'Bearer ' + token) - xhr.upload.addEventListener('progress', (e) => { - if (e.lengthComputable && onProgress) { +/** + * 表单上传(带进度回调)—— 基于 axios request 实例, + * 复用请求拦截器(自动附加 Bearer Token)与响应拦截器(401 自动刷新后重试)。 + * 进度通过 axios onUploadProgress 获取。 + */ +function postFormWithProgress(path: string, formData: FormData, onProgress?: (pct: number) => void): Promise { + return request.post(path, formData, { + // 必须显式指定 multipart/form-data:request 实例默认 Content-Type 为 application/json, + // 若不覆盖,后端会将请求视为非 multipart 而抛 MultipartException(边界由浏览器自动补充)。 + headers: { 'Content-Type': 'multipart/form-data' }, + onUploadProgress: (e) => { + if (e.total && onProgress) { onProgress(Math.round((e.loaded / e.total) * 100)) } - }) - xhr.addEventListener('load', () => { - if (xhr.status === 401) { localStorage.removeItem('sb_token'); localStorage.removeItem('sb_user'); window.dispatchEvent(new Event('auth:unauthorized')); reject(new Error('401')); return } - try { resolve(JSON.parse(xhr.responseText)) } catch { reject(new Error('响应解析失败')) } - }) - xhr.addEventListener('error', () => reject(new Error('网络错误'))) - xhr.addEventListener('abort', () => reject(new Error('上传已取消'))) - xhr.send(formData) - }) + }, + }).then(r => r.data) } /** 上传文件(带进度) */ diff --git a/frontend/src/views/DocUpload.vue b/frontend/src/views/DocUpload.vue index 498b485..085e2b1 100644 --- a/frontend/src/views/DocUpload.vue +++ b/frontend/src/views/DocUpload.vue @@ -15,7 +15,7 @@ - @@ -36,9 +36,10 @@