WebView中Blob文件下载异常:如何获取原PDF链接并正常下载?
问题解答
问题1:让WebView获取原PDF链接而非Blob链接
网站在WebView里生成Blob链接,大概率是页面JS拦截了PDF链接的点击事件,通过URL.createObjectURL把原PDF请求转成Blob URL(通常是为了实现内嵌预览或自定义下载流程)。要拿到原链接,可以通过两种方式处理:
拦截WebView导航请求:
以flutter_inappwebview为例,利用shouldOverrideUrlLoading回调,判断请求目标是否为PDF格式,直接拦截并使用原URL处理下载:controller.shouldOverrideUrlLoading = (controller, navigationAction) async { var requestUrl = navigationAction.request.url.toString(); if (requestUrl.contains(".pdf") && !requestUrl.startsWith("blob:")) { // 此处执行原URL的下载逻辑 await downloadFile(requestUrl); return NavigationActionPolicy.CANCEL; } return NavigationActionPolicy.ALLOW; };注入JS监听点击事件:
在WebView初始化时注入脚本,拦截a标签点击,提取原始href并传给原生:document.addEventListener('click', function(e) { var target = e.target; while (target && target.tagName !== 'A') { target = target.parentNode; } if (target && target.href.includes('.pdf')) { e.preventDefault(); window.flutter_inappwebview.callHandler('getOriginalPdfUrl', target.href); } }, true);随后在Flutter端监听
getOriginalPdfUrl回调,拿到原URL后直接发起下载。
问题2:JS请求为何返回HTML而非PDF
你的XHR请求没有携带浏览器会话中的关键请求头,导致服务器无法识别合法会话,返回了HTML(大概率是登录页或错误页)。浏览器访问Blob URL时会自动继承当前页面的Cookie、Referer等上下文信息,但WebView中单独发起的XHR不会默认携带这些。
修改后的JS代码需补充必要请求头:
var xhr = new XMLHttpRequest(); var blobUrl = "blobUrlPlaceholder"; console.log(blobUrl); xhr.open('GET', blobUrl, true); // 复制当前页面Cookie到请求头 xhr.setRequestHeader('Cookie', document.cookie); // 添加Referer,模拟页面内请求上下文 xhr.setRequestHeader('Referer', window.location.href); // 保持与WebView一致的User-Agent xhr.setRequestHeader('User-Agent', navigator.userAgent); xhr.responseType = 'blob'; xhr.onload = function(e) { if (this.status == 200) { var blob = this.response; var reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = function() { var base64data = reader.result; var base64ContentArray = base64data.split(","); var mimeType = base64ContentArray[0].match(/[^:\s*]\w+\/[\w-+\d.]+(?=[;| ])/)[0]; var decodedFile = base64ContentArray[1]; console.log(mimeType); window.flutter_inappwebview.callHandler('blobToBase64Handler', decodedFile, mimeType); }; } else { console.error('请求失败,状态码:', this.status); } }; xhr.onerror = function() { console.error('XHR请求出错'); }; xhr.send();
另外注意:Blob URL是浏览器临时内部链接,仅在当前页面会话有效,页面刷新或跳转后请求会直接返回404,必须在Blob URL生成后立即处理。
内容的提问来源于stack exchange,提问作者Roman Soviak
相关产品推荐
相关产品推荐

