美文网首页ios 学习程序员iOS学习开发
WKWebView填坑之----加载沙盒图片和音视频文件

WKWebView填坑之----加载沙盒图片和音视频文件

作者: 优米诺 | 来源:发表于2017-03-09 17:02 被阅读4268次

我们APP的核心功能实现方式为:原生和JS交互。这就需要频繁的互传数据,互传数据在这里就先不说,之后写的一篇,可以看这个。WKWebView填坑之----与H5相互交互

最早用的UIWebView,交互没有WebKit方便但也还凑合,主要是太吃内存了,性能太差,而且现在最低支持iOS 8,所以决定换成WebKit,由此开始了这次的填坑之路。

我们前端显示的内容是从沙盒内加载的图片和音乐文件,用UIWebView时是我把文件的本地路径传给前端然后前端直接去访问文件的本地路径就可以了,但是换成WebKit就没办法加载出来资源文件。google了之后发现这是WebKit现在的bug,好吧,没什么好的解决方案,大部分给的都是在文件前加一个localhost,但是也没给出具体的方案实施步骤。这一看就是在本地开了一个类似Apache服务器啊,顿时感觉这思路也是可以。有了思路现在就开始干。

GitHub上有个神器:GCDWebServer,这次就用的这个
pod集成这些就不说了,直接上代码

// 官方给的示例是在AppDelegate里启动本地服务器,但是我这个并没有必要在APP启动时就启动本地服务器,所以我放在了核心功能控制器的viewDidLoad方法内
// 1.导入头文件
#import <GCDWebServer/GCDWebDAVServer.h>
// 2.定义全局属性
@property (nonatomic,strong) GCDWebServer *webSever;

// 3. 主要代码
     _webSever = [[GCDWebServer alloc]init];
    [_webSever addGETHandlerForBasePath:@"/" directoryPath:NSHomeDirectory() indexFilename:nil cacheAge:3600 allowRangeRequests:YES];
    [_webSever startWithPort:80 bonjourName:nil];
// 好了,这就结束了!WTF,这就完了,是的,可以这么说
// 比方说文件存在Library下有一个123的文件
NSString *basePath = @"http://localhost/Library/123"; // 这样就可以访问到这个文件了,我只需要把我的文件名拼上localhost路径然后传给前端,他们拿到这个链接直接访问就可以拿到这个文件了

上面只是代码,还是来点调试过程吧!
进入到APP内的WebView页面,然后

Snip20170309_10.png

对了,这里Safari需要把“开发”选项打开
点击链接后回打开一个网页检查器

Snip20170309_14.png Snip20170309_15.png Untitled.gif

可以看到我们已经可以访问沙盒内容了,如果在mac上开过本地Apache服务器的同学看到这个界面应该一眼就能看出来这是开了一个本地服务器。
至此,大功告成。我只需要把路径告诉前端我的工作就完成了。

忘了说了,在viewDidLoad开启的话在控制器注销时需要把本地服务器停止

// 此页面并没有右滑返回手势
- (void)goBack{
    // 这也是为什么要定义全局属性的原因 
    [_webSever stop];
    _webSever = nil;
    [self.navigationController popViewControllerAnimated:YES];
}

顺便说一下,GCDWebServer我在模拟器上并不能通过IP地址或者localhost来访问。

相关文章

网友评论

  • Yinper:WKWebView 跨域 问题 大家有解决方案了吗?
    本地 html 存在 ajax 请求 跨域, 谁能帮帮我谢谢
  • 拾取灬回忆:完了没看懂。。。。
    拾取灬回忆:还是卡在模拟器可以出图,真机不行
  • 锦鲤跃龙:你好 我的页面是空白的。路径是http://localhost/WEBRESOURCEFILES/APPROVED●138●943460749499830273/dist/index.html?loginType=cd&hash=my-account&firstIn=true。但是打印出来的NSURL是空的
    优米诺:@锦鲤跃龙 你加载本地HTML的目的是什么,你这样还是会跨域访问的
    锦鲤跃龙:我在电脑的浏览器中可以访问到,但是手机上wkwebview就是空白i
    锦鲤跃龙:我的directoryPath设置的是NSDocumentDirectory
  • 章鱼paul帝:--"用UIWebView时是我把文件的本地路径传给前端然后前端直接去访问文件的本地路径就可以"
    我感觉使用UIWebview也会存在跨域问题 目前没有成功 能给下思路吗? 感谢
    优米诺:@章鱼paul帝 UIWebview的跨域问题可以解决,WebKit的暂时无法解决
  • 洁简:加载沙盒确实麻烦 也可以直接放到tmp下直接加载
    洁简:@锦鲤跃龙 也可以直接转为data 然后转为base64使用
    锦鲤跃龙:tmp会被不定时清理呀
  • paintingStyle:作者你好,我将服务器的H5资源文件下载解压过后,
    通过 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0f];这种方式不能访问到真机中的文件,在模拟器可行,在真机沙盒加载HTML文件必须使用你这种方式吗??
  • timeforasong:你好 能给下demo吗?我一直加载不出来,是空白页面。fileURL 和 baseUrl什么区别,没太看懂,我的fileURL传的是全路径http:/localhost/var/mobile/Containers/Data/Application/825E5D7E-E608-49A0-84CB-CC98EBB59AA7/Library/Caches/65%E6%8A%A5%E4%BB%B7(1).pdf -- file:///
    baseUrl是文件的上一级路径http:/localhost/var/mobile/Containers/Data/Application/F1BE3E05-B6BD-43B4-815C-48C9AE24F683/Library/Caches -- file:/// 不知道那块有问题,求解答
    优米诺:首先,你为什么这么设置路径,这样设置路径如果能访问到也就是说所有APP的沙盒你都能访问到了,你觉得有可能吗?
    其次,我建议你先看懂代码,总共也没几行,我写的明明是在APP内的沙盒路径下开启服务器。
  • LibraCoder:我现在遇到的问题也是wkwebview加载不出本地图片,我是先去SDWebImage异步下载图片之后,找到sd的默认存储路径然后替换html中src的路径~请问localhost是自己需要手动拼接到路径中吗?我写了作者的那些代码之后发现打印的路径里没有localhost
    SDWebImageManager *imageManager = [SDWebImageManager sharedManager];
    NSURL *imageUrl = [NSURL URLWithString:src];
    [imageManager diskImageExistsForURL:imageUrl completion:^(BOOL isInCache) {
    if (isInCache) {
    NSString *cacheKey = [imageManager cacheKeyForURL:imageUrl];
    NSString *imagePaths = [imageManager.imageCache defaultCachePathForKey:cacheKey];
    NSString *srcStr = [NSString stringWithFormat:@"img_%zd,%@",index,imagePaths];
    [self.bridge callHandler:@"testJSFunction" data:srcStr responseCallback:^(id responseData) {
    }];
    }else{
    [imageManager loadImageWithURL:imageUrl options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
    } completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
    if (image && finished) {//如果下载成功
    NSString *cacheKey = [imageManager cacheKeyForURL:imageUrl];
    NSString *imagePaths = [imageManager.imageCache defaultCachePathForKey:cacheKey];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSString *srcStr = [NSString stringWithFormat:@"img_%zd,%@",index,imagePaths];
    [self.bridge callHandler:@"testJSFunction" data:srcStr responseCallback:^(id responseData) {

    }];

    });

    }
    }];
    }
    }];
    优米诺:@索罗门 那跟我这边场景差不多了
    1.拷贝html这些个文件到沙盒内
    2.在沙盒根目录或者library内开启GCDServer,所有访问使用localhost,包括加载HTML文件,拼接你的图片路径,把拼接好的路径丢给HTML让它根据这个路径去访问图片,这样就OK
    LibraCoder:@优米诺 html文件是在bundle内,css,js都是在bundle内,现在就是特别懵,不知道该怎么办了
    优米诺:html不能显示本地图片是因为跨域了,无法访问到图片资源,即使你的路径是对的,这是webkit的安全策略导致的。我看你的代码你是拿到了图片的路径但是不同域无法显示出来。你可以采用我的这种办法,你的HTML文件是在bundle内还是在沙盒内?
  • XTShow:您好,请问一下,为什么我的这个webServer在start的步骤就没有成功,返回的Bool为0 ,请问您遇到过吗?
    XTShow:@优米诺 恩恩,这里已经搞定了,是同时开启多个GCDServer的缘故~谢谢PO主的分享:smiley:
    XTShow:已经解决了,确定没用同时开启两个服务,把端口占用了即可!谢谢PO的文章~
    优米诺:这个还真没遇到,0的话就是你的服务没有成功开启,建议你排查下路径,再看下GCDWebServer使用文档,看是不是哪里配置的不正确
  • 96255f2f235c:我使用这种方法完美解决!亲测可行!
    使用下面方法加载页面:
    [self.wkWebView loadFileURL:fileURL allowingReadAccessToURL:baseUrl];
    注意:
    fileURL,是需要加载的HTML文件路径
    baseUrl,是HTML的上一级文件路径.这是坑点,baseUrl和fileURL不能相同!!!!!!
    优米诺:@聪zero 你心态有问题吧!别人都可以就你不行你不从自己那找原因还说别人是骗子,就服你!
    聪zero:还是加载不了沙盒内的图片,骗子
    timeforasong:你好 能给下demo吗?我一直在在不出来,是空白页面。fileURL 和 baseUrl什么区别,没太看懂,我的fileURL传的是全路径http:/localhost/var/mobile/Containers/Data/Application/825E5D7E-E608-49A0-84CB-CC98EBB59AA7/Library/Caches/65%E6%8A%A5%E4%BB%B7(1).pdf -- file:///
    baseUrl是文件的上一级路径http:/localhost/var/mobile/Containers/Data/Application/F1BE3E05-B6BD-43B4-815C-48C9AE24F683/Library/Caches -- file:/// 不知道那块有问题,求解答
  • LD_左岸:看着好复杂的样子 您看我目前的问题照您这个流程搞能成功吗
    NSLog(@"+++最终的htmlString%@+++",html);
    NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ldd.html"];
    [html writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"本地的html文件---%@",path);
    NSURL * url1 = [NSURL fileURLWithPath:path];

    [self.wkWebView loadFileURL:url1 allowingReadAccessToURL:url1];

    #pragma mark -- UIWebView
    UIWebView * webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, self.view.bounds.size.height/2 + 20, self.view.bounds.size.width, self.view.bounds.size.height/2)];

    //[webView loadHTMLString:html baseURL:url];
    [webView loadRequest:[NSURLRequest requestWithURL:url1]];
    [self.view addSubview:webView];

    我是把一个html字符串 写入文件 在沙盒生成了一个H5的文件 这个H5的文件里的图片链接用的本地的 不是http的 新生成的H5文件如下
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Test ios native load webview's image'</title>
    </head>
    <body>
    <h1>Test how to use ios native code to load webview's image and set the image to webview</h1>
    <div>
    <h2>Here has two image urls. We will try to request this two image with ios but not html</h2>
    </div>
    <hr style="color: red;" />
    <img src="/var/mobile/Containers/Data/Application/F7721407-D958-4A2A-ACAC-1E230B12C33C/Documents/5353c07f4c2ea0471b9f3ee36dedcaac" />
    <img src="/var/mobile/Containers/Data/Application/F7721407-D958-4A2A-ACAC-1E230B12C33C/Documents/54edea1f2edd444aaba9d0321d786962" />
    </body>
    </html>
    目前这个H5用UIWebView加载可以 用WKWebView加载不可以 真机上图片出不来 模拟机上可以
    优米诺:@左岸__ 我觉得你没明白开启这个本地服务器的用途,这个是让你访问沙盒文件的,如果你要保存直接获取沙河路径保存就行了,再就是你的webview内的图片是本地的还是网络的?加载HTML文件的话直接丢路径进去就可以了,不用开服务器。
    LD_左岸:@优米诺 我是先把一个H5的文件保存到本地沙盒里 然后打开沙盒找打这个H5文件可以打开 真机上WK不出图片
    我把您说的这个GCDWebServer集成到项目里了
    <code>_webSever = [[GCDWebServer alloc]init];
    [_webSever addGETHandlerForBasePath:@"/" directoryPath:NSHomeDirectory() indexFilename:nil cacheAge:3600 allowRangeRequests:YES];
    [_webSever startWithPort:80 bonjourName:nil];
    // 好了,这就结束了!WTF,这就完了,是的,可以这么说
    // 比方说文件存在Library下有一个123的文件
    NSString *basePath = @"http://localhost/Library/123&quot;; // 这样就可以访问到这个文件了,我只需要把我的文件名拼上localhost路径然后传给前端,他们拿到这个链接直接访问就可以拿到这个文件了
    </code>
    <code>
    NSLog(@"+++最终的htmlString%@+++",html);
    NSString *path = [basePath stringByAppendingPathComponent:@"ldd.html"];

    [html writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"本地的html文件---%@",path);
    NSURL * url1 = [NSURL fileURLWithPath:path];

    [self.wkWebView loadFileURL:url1 allowingReadAccessToURL:url1];
    </code>
    我这么写不成 我应该怎么把我这个H5的字符串和他上面的localhost联系一下 让这个路径是对的 让WK可以加载呢
    优米诺:应该问题是一样的,我的也是在模拟器上就可以,真机就加载不出图片,你可以试试我这个方法,代码没有几行

本文标题:WKWebView填坑之----加载沙盒图片和音视频文件

本文链接:https://www.haomeiwen.com/subject/glowgttx.html