如何使用WKWebView检索文件?

时间:2014-06-28 06:50:06

标签: ios webkit ios8 wkwebview

我要下载文件(CSV)。它位于网站的登录屏幕后面。我想显示WKWebView以允许用户登录,然后让应用程序在登录后下载文件。

我已尝试在用户登录网站后在WKWebView之外下载文件,但会话数据似乎是沙箱,因为它下载的是带有登录表单的html文档而不是想要的文件。

我还尝试在WKUserScript对象中添加WKUserContentController,但在加载非HTML文件时脚本无法运行。

我是否有办法访问此文件,同时允许用户通过WKWebView登录?

5 个答案:

答案 0 :(得分:93)

目前,WKWebView实例将忽略任何默认网络存储(NSURLCache,NSHTTPCookieStorage,NSCredentialStorage)以及可用于自定义网络请求的标准网络类(NSURLProtocol等)。

因此,WKWebView实例的cookie不存储在应用程序的标准Cookie存储中,因此仅使用标准Cookie存储的NSURLSession / NSURLConnection无法访问WKWebView的cookie(这可能就是问题所在你有:“登录状态”很可能存储在cookie中,但NSURLSession / NSURLConnection将不会看到cookie)。

缓存,凭证等也是如此.WKWebView有自己的私有存储,因此不能很好地使用标准的Cocoa网络类。

您也无法自定义请求(添加自己的自定义HTTP标头,修改现有标头等),使用您自己的自定义URL方案等,因为WKWebView也不支持NSURLProtocol。

所以现在WKWebView对许多应用程序来说都没用,因为它不参与Cocoa的标准网络API。

我仍然希望Apple会在iOS 8发布之前对其进行更改,因为否则WKWebView对于许多应用程序来说都是无用的,而且我们可能会更长时间地使用UIWebView。

因此,向Apple发送错误报告,以便Apple了解这些问题是严重的,需要修复。

答案 1 :(得分:15)

您是否检查过请求中的响应Cookie。您可以使用这样的委托方法。

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
    NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];

    for (NSHTTPCookie *cookie in cookies) {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    }

    decisionHandler(WKNavigationResponsePolicyAllow);
}

答案 2 :(得分:1)

我已经完成了类似于您尝试做的事情:

  • 使用网络视图登录
  • 在您的网页浏览中设置navigationDelegate
  • 在您的代理中实施-webView:decidePolicyForNavigationResponse:decisionHandler
  • 调用该委托方法时(在用户登录后),您可以检查navigationResponse.response(将其强制转换为NSHTTPURLResponse*)并查找包含会话信息的Set-Cookie标头您需要经过身份验证的会话。
  • 然后,您可以通过在请求中使用响应中指定的Cookie手动指定Cookie标头来下载CSV。

请注意,委托方法仅用于"主框架"要求。这意味着AJAX请求或内部框架不会触发它。整个页面必须刷新才能工作。

如果您需要触发AJAX请求,iframe等行为,您需要注入一些javascript。

答案 3 :(得分:1)

您可以获取Cookie via Javascript

然后,您可以使用获取的cookie手动下载文件:

webView.evaluateJavaScript("(function() { return document.cookie })()", completionHandler: { (response, error) -> Void in
  let cookie = response as! String
  let request = NSMutableURLRequest(URL: docURL)
  request.setValue(cookie, forHTTPHeaderField:  "Cookie")

  NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
    // Your CSV file will be in the response object
  }).resume()
})

答案 4 :(得分:0)

当我尝试来自userContentController didReceiveScriptMessage的请求时,我似乎没有会话cookie。

但是,当从decisionPolicyForNavigationAction调用时,以下代码检测到我已登录。

     let urlPath: String = "<api endpoint at url at which you are logged in>"

    let url = NSURL(string: urlPath)
    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in

        let string1 = NSString(data: data, encoding: NSUTF8StringEncoding)
        println(string1)
        println(data)
        if(error != nil) {
            println("Error sending token to server")
            // Print any error to the console
            println(error.localizedDescription)
        }
        var err: NSError?

    })

    task.resume()