You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:15:16