H5在WKWebView中读取沙盒文件
最后更新于
最后更新于
当前环境: Xcode10.0 Swift4.2 iOS SDK 12.1
Demo: https://github.com/zColdWater/WKWebView-LoadSandBoxResources
需要加载一个在线的 Web,通过 JSBridge
(不清楚的可以自行 Google 或者看之前我的文章)获取到 Native 的资源路径,比如 file:///private/xxxx/xxx/xx.png
把它显示在 WebView
当中。 举个例子吧: 一个 HTML
的 Image
标签想显示iOS 沙盒里面的资源文件。
看似很简单,但是经过尝试之后我才发现,并不是很容易,还是有一点坑需要踩的。
上面看似简单的需求,但是在实现的路上却遇到了一些麻烦。
首先我们一步一步分析:
我们准备一张图片和一个视频放在沙盒当中。
拿到图片和 MP4 在沙盒中的路径。
在 HTML5 当中,写一个 Image 和 video 标签,把资源路径放上去。
似乎看上去应该就没什么问题了。
然后当我启动 WebServer
后把 H5 部署在我们本地(模拟在线H5
),然后 Native 加载这个 IP 就发现问题了,啥都没显示出来,这令我很伤心,为什么呢? 我去 Google 一大圈,国内热心网友不分青红皂白说这是跨域,然后 WiKi 一下发现跟跨域没什么关系,如果你对跨域不了解,可以点击查看这篇文章。
这里我可以这么解释为什么和跨域限制没关系,如果这算跨域,那么 Image
标签的 src
就只能同域名同端口的资源了,显然显示情况不是了,我可以加载任何域的资源。
现在问题已经很明显了,接下来就是如何解决这个问题了,这是大家最关心的。
方法一:
如果我们从需求入手,H5 同学只需要选取系统相册的一个图片,或者从系统相册中选取一个视频,那么如果可以接受系统的 UI 风格,完全可以用 H5 标签,打开相机,打开相册等,来选取手机的资源文件,在标签绑定回调方法,会接到系统给你回调的文件资源。
这种解决方案,原生同学不同提供任何东西,系统已经帮你搞定了。
方法二:
如果产品设计不能接受这个方案,我们可以使用加载离线包来实现,直白的意思就是,将 H5 打包成 Zip,下载到手机本地,然后加载 WebView 的时候使用 laodFile
这个方法后面跟一个资源可访问权限的目录,你要设置一个比你访问资源目录更上一级目录作为这个根目录。 具体可以参考我的这篇文章,当然如果加载离线包,H5 同学要让服务端处理跨域的限制。
方法三:
查了好多 Stackoverflow
的答案,普遍是将需要加载URL 资源的 HTML 下载到本地,用 wkwebview
的 loadHTMLString
来加载这个页面,这样确实是可以使用 file协议
去加载本地资源,但是也会导致一个问题,Web 资源加载拿不到,不知道是因为跨域 AJAX 请求还是什么情况,具体大家可以用淘宝网试试。 如果有兴趣也可以打开调试工具看下具体原因,这个解决办法要视情况而定。
方法四
其实还有一种通过 Base64 的编码来解决 H5Image 标签显示图片的问题,当然了这里我就不介绍了,如果视频稍微大一点的家伙就不好办了,如果感兴趣可以参考这个例子,或者去 Google 一下就知道了。
最后一种方法可以通过 App 本地开启 Server 服务,Root 开在沙盒目录,然后通过将文件的 file协议
路径转换成本地服务路径,再给 H5 显示,经过测试完全可用。
第一步: 在 Podfile
写入(关于 GCDWebServer,一个轻量级的 AppServer 框架。)
执行 pod install
安装。
在你要使用的地方
不论是图片还是视频都可以加载本地资源,任务完成,Demo 在文章开头。
注意 ️️⚠️: 这里插一句: 如果你运行 Demo 要事先将图片和视频资源放在沙盒目录才行,资源文件我也放在 Demo 里面了,大家自己模拟器运行,打开 Document 文件夹自己放进去就可以了
然后启动你的 App,开启 Server 然后将 file协议
换成你的 App 服务地址,来提供给 H5 如下(你可以用上面的ip,也可以 localhost 都一样的,都是指向你的本机。):
这里我就是开启了一个 npm 的服务,这里就不再赘述了,Demo 里面有大家自行运行就好了。 效果如下: