ios 如何使用 WKWebView 检索文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24464397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I retrieve a file using WKWebView?
提问by Devin McKaskle
There is a file (CSV) that I want to download. It is behind a login screen on a website. I wanted to show a WKWebView
to allow the user to log in and then have the app download the file after they had logged in.
我想下载一个文件 (CSV)。它位于网站上的登录屏幕后面。我想显示一个WKWebView
以允许用户登录,然后在他们登录后让应用程序下载文件。
I've tried downloading the file outside of WKWebView
after the user has logged in to the website, but the session data seems to be sandboxed because it downloads an html document with the login form instead of the desired file.
我尝试WKWebView
在用户登录网站后在外部下载文件,但会话数据似乎被沙盒化,因为它下载了一个带有登录表单的 html 文档,而不是所需的文件。
I've also tried adding a WKUserScript
to the WKUserContentController
object, but the script doesn't get run when a non-HTML file is loaded.
我也尝试添加WKUserScript
到WKUserContentController
对象,但是当加载非HTML文件中的脚本没有得到执行。
Is there a way for me to access this file while allowing users to log in via the WKWebView
?
有没有办法让我访问此文件,同时允许用户通过WKWebView
?
回答by Alex
Right now, WKWebView instances will ignore any of the default networking storages (NSURLCache, NSHTTPCookieStorage, NSCredentialStorage) and also the standard networking classes you can use to customize the network requests (NSURLProtocol, etc.).
现在,WKWebView 实例将忽略任何默认网络存储(NSURLCache、NSHTTPCookieStorage、NSCredentialStorage)以及可用于自定义网络请求的标准网络类(NSURLProtocol 等)。
So the cookies of the WKWebView instance are not stored in the standard Cookie storage of your App, and so NSURLSession/NSURLConnection which only uses the standard Cookie storage has no access to the cookies of WKWebView (and exactly this is probably the problem you have: the ?login status“ is most likely stored in a cookie, but NSURLSession/NSURLConnection won't see the cookie).
因此 WKWebView 实例的 cookie 没有存储在您的应用程序的标准 Cookie 存储中,因此仅使用标准 Cookie 存储的 NSURLSession/NSURLConnection 无法访问 WKWebView 的 cookie(这可能正是您遇到的问题: “登录状态”很可能存储在 cookie 中,但 NSURLSession/NSURLConnection 不会看到 cookie)。
The same is the case for the cache, for the credentials etc. WKWebView has its own private storages and therefore does not play well with the standard Cocoa networking classes.
缓存、凭据等的情况也是如此。 WKWebView 有自己的私有存储,因此不能很好地与标准 Cocoa 网络类配合使用。
You also can't customize the requests (add your own custom HTTP headers, modify existing headers, etc), use your own custom URL schemes etc, because also NSURLProtocol is not supported by WKWebView.
您也无法自定义请求(添加您自己的自定义 HTTP 标头、修改现有标头等)、使用您自己的自定义 URL 方案等,因为 WKWebView 也不支持 NSURLProtocol。
So right now WKWebView is pretty useless for many Apps, because it does not participate with the standard networking APIs of Cocoa.
所以现在 WKWebView 对许多应用程序来说是毫无用处的,因为它不参与 Cocoa 的标准网络 API。
I still hope that Apple will change this until iOS 8 gets released, because otherwise WKWebView will be useless for many Apps, and we are probably stick with UIWebView a little bit longer.
我仍然希望 Apple 能够在 iOS 8 发布之前改变这一点,否则 WKWebView 对许多应用程序将毫无用处,我们可能会更长时间地使用 UIWebView。
So send bug reports to Apple, so Apple gets to know that these issues are serious and needs to be fixed.
所以向苹果发送错误报告,让苹果知道这些问题很严重,需要修复。
回答by Nick Anger
Have you checked the response cookies coming back from the request. You could use a delegate method like this.
您是否检查了从请求中返回的响应 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);
}
回答by Sebastien Martin
I've accomplished something similar to what you're trying to do:
我已经完成了类似于你想要做的事情:
- use the web view to login as you're already doing
- set a
navigationDelegate
on your webview - implement
-webView:decidePolicyForNavigationResponse:decisionHandler
in your delegate - when that delegate method is called (after the user logs in), you can inspect
navigationResponse.response
(cast it toNSHTTPURLResponse*
) and look for aSet-Cookie
header that contains the session info you'll need for authenticated sessions. - you can then download the CSV by manually specifying the
Cookie
header in your request with the cookies specified in the response.
- 使用 Web 视图登录,就像您已经在做的那样
navigationDelegate
在你的 webview 上设置一个-webView:decidePolicyForNavigationResponse:decisionHandler
在您的委托中实施- 当调用该委托方法时(在用户登录后),您可以检查
navigationResponse.response
(将其转换为NSHTTPURLResponse*
)并查找Set-Cookie
包含身份验证会话所需的会话信息的标头。 - 然后,您可以通过
Cookie
使用响应中指定的 cookie手动指定请求中的标头来下载 CSV 。
Note that the delegate methods are only called for "main frame" requests. Which means that AJAX requests or inner frames will not trigger it. The whole page must refresh for this to work.
请注意,仅针对“主框架”请求调用委托方法。这意味着 AJAX 请求或内部框架不会触发它。整个页面必须刷新才能工作。
If you need to trigger behavior for AJAX requests, iframes etc you'll need to inject some javascript.
如果您需要触发 AJAX 请求、iframe 等的行为,您需要注入一些 javascript。
回答by Pieter Meiresone
You can obtain the cookie via Javascript:
您可以通过 Javascript获取 cookie :
You could then use the obtained cookie to download the file manually:
然后,您可以使用获得的 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()
})
回答by moonhead
I do not seem to have the session cookie when I try a request from userContentController didReceiveScriptMessage.
当我尝试来自 userContentController didReceiveScriptMessage 的请求时,我似乎没有会话 cookie。
However, when called from decidePolicyForNavigationAction, the following code detects that I'm logged in.
但是,当从decidePolicyForNavigationAction 调用时,以下代码检测到我已登录。
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()