日常记录-识别游览器地址栏参数内容值失败的原因
最近工作中临时被指派排查一个问题,预览文件时,会导致预览页面的其它元素隐藏。之后拉取代码发现,进入页面后会通过一个获取地址栏参数的方法获取地址栏中传入的参数信息去处理业务信息。
// 获取地址栏参数
export function GetQueryString(name) {
let reg: any = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
let r = window.location.search.substr(1).match(reg) //获取url中"?"符后的字符串并正则匹配
let context = ''
if (r != null) {
context = decodeURIComponent(r[2])
}
reg = null
r = null
return context == null || context == '' || context == 'undefined' ? '' : context
}
最终排查传入的地址栏参数,发现出现问题是因为地址栏中传入了预览的文件名称。且文件名称包含了特殊字符导致程序上识别失败。
示例:文件名: 16#测试文件名称

实际运行之后发现返回结果不对

文件名被截断了,并且导致后面的参数获取也出现问题。而导致这样的原因是因为 # 字符在URL中属于特殊字符,它表示 URL 的片段标识符(fragment),从而其后的部分不会包含在 window.location.search 中,这也就能解释为什么后面console中都是空字符。
解决方案:
方案一:针对#字符进行处理(不足点: 无法满足所有的场景, 如果文件名包含其它字符 类似 % & 同样也会出现不能完整获取名称的情况)
export function GetQueryString(name) {
const url = window.location.href
// 构建正则表达式,注意处理参数值中可能包含 # 符号的情况
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
// 先获取完整的 URL 中 ? 后面的部分
const queryString = url.split('?')[1] || ''
let match = queryString.match(reg)
let context = ''
if (match) {
// 提取参数值
context = decodeURIComponent(match[2])
// 检查参数值是否被截断(因为包含 # 符号)
if (context.includes('#')) {
// 找到参数在 URL 中的完整位置
const paramStart = url.indexOf(name + '=')
if (paramStart !== -1) {
// 找到下一个 & 符号的位置
const nextAmp = url.indexOf('&', paramStart)
// 如果没有下一个 &,则取到 URL 末尾
const paramEnd = nextAmp !== -1 ? nextAmp : url.length
// 提取完整的参数值
const fullParam = url.substring(paramStart + name.length + 1, paramEnd)
context = decodeURIComponent(fullParam)
}
}
}
return context == null || context == '' || context == 'undefined' ? '' : context
}
方案二:业务逻辑进行修改,外面不传入文件名称,进入预览页面之后,通过接口从后端获取文件名称(这样可以万无一失,但是针对目前业务场景不满足)
方案三:针对可能存在特殊字符的字段,在跳转进预览之前,进行内容编码加密,并在进入页面之后,通过获取地址栏参数函数进行解密(encodeURIComponent 加密 decodeURIComponent 解密)

方案三进阶:(亮点:现代浏览器推荐使用 URLSearchParams 来解析查询参数,它更简洁、安全,且能自动处理编码,无需手动解码, 这个方法同样能正确解码 encodeURIComponent 编码的值,且避免正则表达式可能存在的边界问题(如参数值中包含 & 或 = 但未编码的情况))
export function GetQueryString(name) {
const context = new URLSearchParams(window.location.search).get(name) || ''
return context == null || context == '' || context == 'undefined' ? '' : context
}

浙公网安备 33010602011771号