Web Share API分享文件为何会生成随机文件名?
问题成因
该问题属于安卓端Chromium内核(覆盖安卓Chrome、绝大多数国产套壳移动端浏览器)的Web Share API实现缺陷,和业务代码逻辑无关:内核在将文件传递给系统分享组件时,没有透传File对象构造时传入的name属性,系统层拿不到原始文件元数据,就会自动生成share+随机数字.pdf格式的默认文件名。
分享弹窗标题能正常显示自定义名称,是因为navigator.share接收的title参数属于独立的文本渲染字段,和实际传输的文件元数据走不同的传递链路,因此会出现UI显示正确、落地文件名错误的割裂现象。
你查到的W3C仓库issue没有给出解决方案,是因为这个问题不属于规范层面的缺陷,是浏览器厂商的实现bug,且不同安卓版本、不同浏览器内核版本的表现不一致,没有统一的规范层面修复方式。
可行修复方案
按落地优先级排序:
- 补全文件元数据,兼容内核读取逻辑
不要直接拿jsPDF输出的Blob构造File,先手动给Blob实例挂载完整的文件元数据,同时在share参数中增加text字段做文件名兜底,并且补全navigator.canShare的参数校验(原代码只判断方法存在,没有校验当前环境是否支持PDF文件分享)。修正后的代码如下:
if (navigator.canShare && navigator.userAgentData?.mobile) { // 生成PDF原始blob const pdfBlob = doc.output('blob'); // 手动补全blob元数据,覆盖内核默认读取逻辑 pdfBlob.name = `${doc_name}.pdf`; pdfBlob.lastModified = Date.now(); // 构造File对象时同步传入完整参数 const shareFiles = [ new File([pdfBlob], `${doc_name}.pdf`, { type: 'application/pdf', lastModified: pdfBlob.lastModified }) ]; // 校验当前环境是否支持目标文件分享 if (!navigator.canShare({ files: shareFiles })) { // 不支持则走原生下载兜底 const objUrl = URL.createObjectURL(pdfBlob); const downloadAnchor = document.createElement('a'); downloadAnchor.href = objUrl; downloadAnchor.download = `${doc_name}.pdf`; downloadAnchor.click(); URL.revokeObjectURL(objUrl); return; } try { await navigator.share({ title: `${doc_name}.pdf`, text: `${doc_name}.pdf`, // 部分低版本内核会读取text字段作为落地文件名 files: shareFiles }); } catch (err) { showBanner(err.message, bannerState.ERROR, ALERT_PARENT, ALERT_TIME); } }
- 针对低内核版本做降级处理
安卓Chrome 110以下版本、微信/QQ等内置浏览器的Web Share实现存在不可逆的元数据丢失问题,这类环境下不要调用navigator.share,直接走自定义下载逻辑即可,没有其他修复路径。 - 特定渠道适配
若分享目标为国内社交类应用,这类应用本身会对接收的分享文件做二次重命名,即使浏览器层正确传递了文件名,也可能被平台规则替换,可以在用户选择对应分享渠道时增加轻提示,告知用户可手动修改文件名。
注意:不要尝试通过修改File原型、伪造本地文件路径的方式修复,这类操作已经被高版本浏览器的安全策略拦截,会直接触发分享失败。
内容的提问来源于stack exchange,提问作者ariver
相关产品推荐
相关产品推荐

