From be5e5f76b213920fb3b660635b732f36a467e00a Mon Sep 17 00:00:00 2001 From: JiangSheng Date: Thu, 27 Nov 2025 10:16:31 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=B8=8B=E8=BD=BD=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/request.ts | 55 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/src/api/request.ts b/src/api/request.ts index 5a40f0b..27cad88 100644 --- a/src/api/request.ts +++ b/src/api/request.ts @@ -84,25 +84,52 @@ const download = (url: string, params = {}, filename = 'download') => { let fileName = filename; if (contentDisposition) { - const regex = /(filename\*?)\s*=\s*(?:UTF-8'')?["']?([^;"']+)["']?/ig; - let match: RegExpExecArray | null = null; - while ((match = regex.exec(contentDisposition)) !== null) { - const key = match[1]; - const val = match[2]; - if (!val) continue; - if (key.endsWith('*')) { - if (val.toLowerCase() === 'utf-8') { - continue; - } + const parts = contentDisposition.split(';').map((p: string) => p.trim()).filter(Boolean); + const paramsMap: Record = {}; + parts.forEach((part: string) => { + const idx = part.indexOf('='); + if (idx === -1) return; + const key = part.slice(0, idx).trim().toLowerCase(); + let val = part.slice(idx + 1).trim(); + if (val.startsWith('"') && val.endsWith('"')) { + val = val.slice(1, -1); + } + paramsMap[key] = val; + }); + + if (paramsMap['filename*']) { + const val = paramsMap['filename*']; + const rfcMatch = val.match(/^([^']*)''(.*)$/); + if (rfcMatch) { + const encoded = rfcMatch[2]; try { - fileName = decodeURIComponent(val); + fileName = decodeURIComponent(encoded); } catch { - fileName = val; + fileName = encoded; } } else { - fileName = val.replace(/^["']|["']$/g, ''); + if (/^utf-?8$/i.test(val) && paramsMap['filename']) { + const candidate = paramsMap['filename']; + try { + fileName = candidate.includes('%') ? decodeURIComponent(candidate) : candidate; + } catch { + fileName = candidate; + } + } else { + try { + fileName = val.includes('%') ? decodeURIComponent(val) : val; + } catch { + fileName = val; + } + } + } + } else if (paramsMap['filename']) { + const candidate = paramsMap['filename']; + try { + fileName = candidate.includes('%') ? decodeURIComponent(candidate) : candidate; + } catch { + fileName = candidate; } - break; } }