【问题标题】:WKWebView: How to handle BLOB URLWKWebView:如何处理 BLOB URL
【发布时间】:2020-08-25 09:11:59
【问题描述】:

当我点击一个文件下载它时,我有我的WKWebView。我有一个弹窗文字:

没有应用程序配置打开 URL blob:https// ...

我尝试将自定义 URL 方案 blob 注册到 WKWebView,应用程序崩溃说默认情况下已经支持此方案。

但是,当我单击文件时,不会调用委托:

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void)`

所以我什至不知道何时单击 blob url 以尝试通过注入 JavaScript 下载文件。

我的应用程序适用于 macOS。

【问题讨论】:

  • 是的,我正在尝试打开一个 url blob。看帖子我加了图
  • 如果 JavaScript 中有解决方案,我将接受解决方案。如何将 blob url 监听到 javascript 并更改方案?你有代码的想法吗?我已经做过研究,但没有成功
  • 如果没有其他方法,您可以尝试使用 dataurl。但看看设置 CSP 是否有效:<meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline' 'unsafe-eval' 'self' gap://ready file: ws://<path-to-ws-endpoint>; child-src * 'unsafe-inline' 'unsafe-eval' blob: cdvfile:; img-src * 'self' data: blob:;" />
  • 这家伙找到了一种解决方法,我猜它比必须转换为 dataurl 略好:stackoverflow.com/questions/45065085/…
  • 我无权访问站点代码。所以我必须注入'你能向我解释你建议我的代码吗

标签: swift macos wkwebview


【解决方案1】:

请注意,这是一个非常迂回的 hack。扫描所有 href 并用 datauri 替换检测到的任何 blob url。 编辑:更新以显示它正在运行

function blobToDataURL(blob, callback) {
    var a = new FileReader();
    a.onload = function(e) {callback(e.target.result);}
    a.readAsDataURL(blob);
}
// not sure what elements you are going to intercept:
document.querySelectorAll('a').forEach(async (el)=>{
   const url = el.getAttribute('href');
   if( url.indexOf('blob:')===0 ) {
       let blob = await fetch(url).then(r => r.blob());
       blobToDataURL(blob, datauri => el.setAttribute('href',datauri));
   }
});

b=new Blob([new Int8Array([1,2,3,4,5,6,7,8,9,10]).buffer]);
test.href=URL.createObjectURL(b);
b=new Blob([new Int8Array([31,32,33,34,35]).buffer]);
test1.href=URL.createObjectURL(b);
b=new Blob([new Int8Array([51,52,53,54]).buffer]);
test2.href=URL.createObjectURL(b);



function blobToDataURL(blob, callback) {
    var a = new FileReader();
    a.onload = function(e) {callback(e.target.result);}
    a.readAsDataURL(blob);
}

document.addEventListener('click', function(event) {
  event.preventDefault();
  if ( event.target.matches('a[href^="blob:"]') )
     (async el=>{
       const url = el.href;
       const blob = await fetch(url).then(r => r.blob());
       blobToDataURL(blob, datauri => el.href=datauri);
     })(event.target);
});

// not sure what elements you are going to intercept:
/*document.querySelectorAll('a').forEach(async (el)=>{
   const url = el.href;
   if( url.indexOf('blob:')===0 ) {
       let blob = await fetch(url).then(r => r.blob());
       blobToDataURL(blob, datauri => el.href=datauri);
   }
});*/
<a id="test">test</a>
<a id="test1">test</a>
<a id="test2">test</a>

点击时数据uri转换示例:

b=new Blob([new Int8Array([1,2,3,4,5,6,7,8,9,10]).buffer]);
test.href=URL.createObjectURL(b);
b=new Blob([new Int8Array([31,32,33,34,35]).buffer]);
test1.href=URL.createObjectURL(b);
b=new Blob([new Int8Array([51,52,53,54]).buffer]);
test2.href=URL.createObjectURL(b);



function blobToDataURL(blob, callback) {
    var a = new FileReader();
    a.onload = function(e) {callback(e.target.result);}
    a.readAsDataURL(blob);
}

document.addEventListener('click', function(event) {
  if ( event.target.matches('a[href^="blob:"]') ) {
     event.preventDefault();
     (async el=>{
       const url = el.href;
       const blob = await fetch(url).then(r => r.blob());
       blobToDataURL(blob, datauri => window.open(el.href=datauri,el.target||'_self'));
     })(event.target);
   }
});

// not sure what elements you are going to intercept:
/*document.querySelectorAll('a').forEach(async (el)=>{
   const url = el.href;
   if( url.indexOf('blob:')===0 ) {
       let blob = await fetch(url).then(r => r.blob());
       blobToDataURL(blob, datauri => el.href=datauri);
   }
});*/
<a id="test">test</a>
<a id="test1">test</a>
<a id="test2">test</a>

【讨论】:

  • 如果我不想扫描 blob 链接,但在单击 blob 链接后立即收听怎么办?因为在 webapp 中,链接并不总是在主页上,而是在点击按钮后
  • 使用 addEventListener 代替。异步回调可能会让人尴尬。只要确保你防止默认
  • 做一个addEventListener,页面加载时元素必须存在?或者在窗口中添加一个监听器?能给我举个例子吗
  • 对,您必须在 DOM 准备好后执行它。我不确定将其注入 WebView 是否会导致任何差异。它很可能不应该。请记住,这基本上是在每次点击后进行 base64 转换。大文件可能不是一个好主意。如果那个 SO 链接可以工作,它可能会比这更好。
  • 感谢您的宝贵帮助
猜你喜欢
  • 1970-01-01
  • 2018-11-25
  • 2021-12-03
  • 1970-01-01
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 2018-09-11
相关资源
最近更新 更多