36

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

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

我也尝试将 a 添加WKUserScriptWKUserContentController对象中,但加载非 HTML 文件时脚本不会运行。

有没有办法让我在允许用户通过登录的同时访问这个文件WKWebView

4

5 回答 5

96

现在,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 更长时间。

所以向苹果发送错误报告,让苹果知道这些问题很严重,需要修复。

于 2014-07-27T15:00:30.350 回答
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);
}
于 2014-12-12T19:36:05.833 回答
1

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

  • 使用 Web 视图登录,就像您已经在做的那样
  • navigationDelegate在你的 webview 上设置一个
  • -webView:decidePolicyForNavigationResponse:decisionHandler在您的委托中实施
  • 当调用该委托方法时(在用户登录后),您可以检查navigationResponse.response(将其转换为NSHTTPURLResponse*)并查找Set-Cookie包含经过身份验证的会话所需的会话信息的标头。
  • 然后,您可以通过使用响应中指定的 cookie 手动指定Cookie请求中的标头来下载 CSV。

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

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

于 2015-02-25T12:40:27.337 回答
1

您可以通过 Javascript获取 cookie :

然后,您可以使用获得的 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()
})
于 2016-03-14T07:37:34.133 回答
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()
于 2015-07-10T02:30:42.897 回答