【iOS】WKWebView访问本地文件遇到的问题及解决方案

本文介绍了在iOS开发中使用WKWebView遇到的四个问题:访问index.html、无权限访问本地文件、访问沙盒文件以及加载本地3D模型。针对这些问题提出了相应的解决方案,包括设置WKWebView配置、文件拷贝、协议拦截以及返回正确类型的URLResponse。

使用WKWebView加载3D模型,3D模型是使用webGL开发的,考虑到网络问题,采用本地化的方式,将3D模型数据下载到本地沙盒,将JS代码放入到工程目录下,再使用WKWebView加载index.html。

问题一:WKWebView访问index.html

由于JS代码中是通过文件路径找访问其他JS文件,所以在将js代码导入到项目中时,要创建实体文件夹才能够正常访问,如下图:

问题二:WKWebView无权限访问本地文件

1、访问本地文件使用的是file://协议,由于WKWebView的安全机制,会报一些错无法访问到。需要打开webView的file://协议访问权限,设置`allowFileAccessFromFileURLs`为`true`。

2、如果出现跨域的报错,也可以通过设置`allowUniversalAccessFromFileURLs`为`true`来解决。

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// 解决HTML请求跨域
[config setValue:@(true) forKey:@"allowUniversalAccessFromFileURLs"];
​
WKPreferences *preferences = [[WKPreferences alloc] init];
// 打开web访问本地文件权限
[preferences setValue:@(true) forKey:@"allowFileAccessFromFileURLs"];
config.preferences = preferences;

问题三:WKWebView访问沙盒文件

WKWebView无法访问Documents文件夹下的内容,只能访问tmp文件夹,因为下载的文件是放在Documents文件夹下的,所以有下面两个解决方案:

方案一、将文件拷贝到tmp文件夹下访问

通过文件管理类`NSFileManager`进行文件的拷贝,但是由于下载的文件比较大,并且会有文件更新的情况,如果每次都拷贝的话,拷贝的时间比较长,很影响用户体验。

+ (void)copyFileFromPath:(NSString *)sourcePath toPath:(NSString *)toPath {
   NSFileManager *fileManager = [NSFileManager defaultManager];
   // 判断目标位置 id 文件夹是否存在
   if ([fileManager fileExistsAtPath:toPath]) {
       // 存在,先移除
      [fileManager removeItemAtPath:toPath error:nil];
  }
   // 不存在 先创建 目标位置 id 文件夹
   BOOL toSuccess = [fileManager createDirectoryAtPath:toPath withIntermediateDirectories:YES attributes:nil error:nil];
   if (toSuccess) {
       // 获取fromPath文件路径下所有文件
       NSArray* array = [fileManager contentsOfDirectoryAtPath:sourcePath error:nil];
       for(int i = 0; i<[array count]; i++) {
           NSString *fullPath = [sourcePath stringByAppendingPathComponent:[array objectAtIndex:i]];
           NSString *fullToPath = [toPath stringByAppendingPathComponent:[array objectAtIndex:i]];
           // 判断是否存在并且为文件夹
           BOOL isFolder = NO;
           BOOL isExist = [fileManager fileExistsAtPath:fullPath isDirectory:&isFolder];
           if (isExist && isFolder) {
               // 存在并且是文件夹,在toPath下创建
              [fileManager createDirectoryAtPath:fullToPath withIntermediateDirectories:YES attributes:nil error:nil];
              [self copyFileFromPath:fullPath toPath:fullToPath];
          } else if (isExist && !isFolder) {
               NSError *err = nil;
              [fileManager copyItemAtPath:fullPath toPath:fullToPath error:&err];
          } else {
               NSLog(@"未找到源文件");
          }
      }
  }
   
}

方案二、拦截file://协议,使用原生获取本地沙盒文件,再将数据传给JS

该方案的具体实现可参考另一篇文章《WKWebView实现请求拦截,http/https/file等》

问题四:加载本地3D模型的时候,无法显示

在拦截file://请求之后,需要回传给webView请求任务一个response,在生成response的时候有两种方式`NSURLResponse`和`NSHTTPURLResponse`两种方式,使用`NSHTTPURLResponse`方式生成可以正常加载。(可参考另一篇文章《WKWebView实现请求拦截,http/https/file等》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值