H5 在 WKWebView 中读取沙盒文件

发布于 2024-08-07 11:12:52 字数 4227 浏览 14 评论 0

当前环境: Xcode10.0 Swift4.2 iOS SDK 12.1

需求

需要加载一个在线的 Web,通过 JSBridge (不清楚的可以自行 Google 或者看之前我的文章) 获取到 Native 的资源路径,比如 file:///private/xxxx/xxx/xx.png 把它显示在 WebView 当中。  举个例子吧: 一个 HTMLImage 标签想显示iOS 沙盒里面的资源文件。

<image src="file:///private/xxxx/xxx/xx.png"></image>

看似很简单,但是经过尝试之后我才发现,并不是很容易,还是有一点坑需要踩的。

遇到问题

上面看似简单的需求,但是在实现的路上却遇到了一些麻烦。

首先我们一步一步分析:

我们准备一张图片和一个视频放在沙盒当中。

拿到图片和 MP4 在沙盒中的路径。

在 HTML5 当中,写一个 Image 和 video 标签,把资源路径放上去。

似乎看上去应该就没什么问题了。

然后当我启动 WebServer 后把 H5 部署在我们本地( 模拟在线 H5 ),然后 Native 加载这个 IP 就发现问题了,啥都没显示出来,这令我很伤心,为什么呢? 我去 Google 一大圈,国内热心网友不分青红皂白说这是跨域,然后 WiKi 一下发现跟跨域没什么关系,如果你对跨域不了解,可以点击查看 这篇文章

这里我可以这么解释为什么和跨域限制没关系,如果这算跨域,那么 Image 标签的 src 就只能同域名同端口的资源了,显然显示情况不是了,我可以加载任何域的资源。

解决问题

现在问题已经很明显了,接下来就是如何解决这个问题了,这是大家最关心的。

方法一:

如果我们从需求入手,H5 同学只需要选取系统相册的一个图片,或者从系统相册中选取一个视频,那么如果可以接受系统的 UI 风格,完全可以用 H5 标签,打开相机,打开相册等,来选取手机的资源文件,在标签绑定回调方法,会接到系统给你回调的文件资源。

这种解决方案,原生同学不同提供任何东西,系统已经帮你搞定了。

方法二:

如果产品设计不能接受这个方案,我们可以使用加载离线包来实现,直白的意思就是,将 H5 打包成 Zip,下载到手机本地,然后加载 WebView 的时候使用 laodFile 这个方法后面跟一个资源可访问权限的目录,你要设置一个比你访问资源目录更上一级目录作为这个根目录。 具体可以参考我的 这篇文章 ,当然如果加载离线包,H5 同学要让服务端处理跨域的限制。

方法三:

查了好多 Stackoverflow 的答案,普遍是将需要加载URL 资源的 HTML 下载到本地,用 wkwebviewloadHTMLString 来加载这个页面,这样确实是可以使用 file 协议 去加载本地资源,但是也会导致一个问题,Web 资源加载拿不到,不知道是因为跨域 AJAX 请求还是什么情况,具体大家可以用淘宝网试试。 如果有兴趣也可以打开调试工具看下具体原因,这个解决办法要视情况而定。

方法四

其实还有一种通过 Base64 的编码来解决 H5Image 标签显示图片的问题,当然了这里我就不介绍了,如果视频稍微大一点的家伙就不好办了,如果感兴趣可以参考 这个例子 ,或者去 Google 一下就知道了。

最后一种方法可以通过 App 本地开启 Server 服务,Root 开在沙盒目录,然后通过将文件的 file 协议 路径转换成本地服务路径,再给 H5 显示,经过测试完全可用。

第一步: 在 Podfile 写入(关于 GCDWebServer ,一个轻量级的 AppServer 框架。)

  pod "GCDWebServer", "~> 3.0"

执行 pod install 安装。

在你要使用的地方

import GCDWebServer

/// 启动 Server 参数自己定,但是 directoryPath 和 forBasePath 要定义好,我们写的是沙盒路径。
func initWebServer() {
    let webServer = GCDWebServer()
    webServer.addGETHandler(forBasePath: "/", directoryPath: NSHomeDirectory(), indexFilename: nil, cacheAge: 3600, allowRangeRequests: true)
    webServer.start(withPort: 9999, bonjourName: "GCD Web Server")
    print("Visit \(webServer.serverURL) in your web browser")
}

然后启动你的 App,开启 Server

然后将 file 协议 换成你的 App 服务地址,来提供给 H5 如下(你可以用上面的ip,也可以 localhost 都一样的,都是指向你的本机。):

这里我就是开启了一个 npm 的服务,这里就不再赘述了,Demo 里面有大家自行运行就好了。 效果如下:

不论是图片还是视频都可以加载本地资源,任务完成,Demo 在文章开头。

注意: 这里插一句: 如果你运行 Demo 要事先将图片和视频资源放在沙盒目录才行,资源文件我也放在 Demo 里面了,大家自己模拟器运行,打开 Document 文件夹自己放进去就可以了

Demo: https://github.com/zColdWater/WKWebView-LoadSandBoxResources

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

0 文章
0 评论
22 人气
更多

推荐作者

lee_heart

文章 0 评论 0

往事如风

文章 0 评论 0

春风十里

文章 0 评论 0

纸短情长

文章 0 评论 0

qq_pdEUFz

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文