32 lines
1.8 KiB
JavaScript
32 lines
1.8 KiB
JavaScript
/** 不依赖小程序中可能不存在的 URL 构造器,不接受任意下载主机。 */
|
||
export function validateContractDocument(query, storageBase) {
|
||
const url = String(query?.url || '')
|
||
const type = String(query?.type || '').toLowerCase()
|
||
const base = String(storageBase || '').replace(/\/$/, '')
|
||
if (!['pdf', 'docx'].includes(type)) throw new Error('不支持的文档格式')
|
||
if (!/^https?:\/\/[^/@?#]+(?:\/[^?#]*)?$/.test(base) || !url.startsWith(base + '/')) {
|
||
throw new Error('无效的文档地址')
|
||
}
|
||
const path = url.split(/[?#]/)[0]
|
||
let decoded
|
||
try { decoded = decodeURIComponent(path) } catch { throw new Error('无效的文档地址') }
|
||
if (/[\\\s\x00-\x1f]/.test(url) || decoded.split('/').some((part) => part === '..' || part === '.')) {
|
||
throw new Error('无效的文档地址')
|
||
}
|
||
return { url, type, name: String(query?.name || `合同.${type}`) }
|
||
}
|
||
|
||
/** 保留微信下载错误用于排查,但不展示含临时签名的文件地址。 */
|
||
export function contractDownloadErrorMessage(error, url) {
|
||
const raw = String(error?.errMsg || '')
|
||
const origin = String(url || '').match(/^https?:\/\/[^/?#]+/)?.[0] || '文件存储域名'
|
||
if (/url not in domain list|domain.*not.*allowed|域名.*不.*合法/i.test(raw)) {
|
||
return `下载被微信拦截:请管理员将 ${origin} 加入小程序的 downloadFile 合法域名,更新配置后重新进入小程序。`
|
||
}
|
||
const detail = raw.replace(/https?:\/\/[^\s]+/gi, '[下载地址]')
|
||
.replace(/[\r\n\t]/g, ' ').replace(/^downloadFile:fail\s*/i, '').trim().slice(0, 180)
|
||
const code = error?.errno ?? error?.errCode
|
||
const codeText = Number.isFinite(Number(code)) && code != null ? `(错误码 ${Number(code)})` : ''
|
||
return detail ? `下载失败:${detail}${codeText}` : `下载失败${codeText},请检查网络或稍后重试`
|
||
}
|