Как я могу получить файл, используя WKWebView?
Есть файл (CSV), который я хочу скачать. Он находится за экраном входа на веб-сайте. Я хотел показать WKWebView
чтобы позволить пользователю войти в систему, а затем приложение загрузить файл после того, как он вошел в систему.
Я пытался загрузить файл за пределами WKWebView
после того, как пользователь вошел на веб-сайт, но данные сеанса кажутся изолированными, потому что он загружает HTML-документ с формой входа вместо желаемого файла.
Я также попытался добавить WKUserScript
к WKUserContentController
объект, но скрипт не запускается при загрузке файла, отличного от HTML.
Есть ли способ для меня, чтобы получить доступ к этому файлу, позволяя пользователям войти через WKWebView
?
5 ответов
Прямо сейчас экземпляры WKWebView будут игнорировать любое из сетевых хранилищ по умолчанию (NSURLCache, NSHTTPCookieStorage, NSCredentialStorage), а также стандартные сетевые классы, которые можно использовать для настройки сетевых запросов (NSURLProtocol и т. Д.).
Таким образом, файлы cookie экземпляра WKWebView не хранятся в стандартном хранилище файлов cookie вашего приложения, и поэтому NSURLSession/NSURLConnection, который использует только стандартное хранилище файлов cookie, не имеет доступа к файлам cookie WKWebView (и именно это, вероятно, является вашей проблемой: "статус входа в систему", скорее всего, хранится в куки, но NSURLSession/NSURLConnection не увидит куки).
То же самое относится и к кешу, к учетным данным и т. Д. WKWebView имеет свои собственные частные хранилища и поэтому не очень хорошо работает со стандартными сетевыми классами Какао.
Вы также не можете настраивать запросы (добавлять собственные настраиваемые заголовки HTTP, изменять существующие заголовки и т. Д.), Использовать свои собственные схемы URL-адресов и т. Д., Поскольку также NSURLProtocol не поддерживается WKWebView.
Так что сейчас WKWebView довольно бесполезен для многих приложений, потому что он не участвует со стандартными сетевыми API-интерфейсами Какао.
Я все еще надеюсь, что Apple изменит это, пока не выйдет iOS 8, потому что в противном случае WKWebView будет бесполезен для многих приложений, и мы, вероятно, будем придерживаться UIWebView немного дольше.
Так что отправляйте отчеты об ошибках в Apple, чтобы Apple узнала, что эти проблемы серьезны и должны быть исправлены.
Вы проверяли ответные куки, возвращающиеся с запроса. Вы можете использовать такой метод делегата.
- (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);
}
Вы можете получить cookie через 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()
})
Я достиг чего-то похожего на то, что вы пытаетесь сделать:
- используйте веб-вид для входа, как вы уже делаете
- установить
navigationDelegate
на вашем сайте - воплощать в жизнь
-webView:decidePolicyForNavigationResponse:decisionHandler
в вашем делегате - когда вызывается этот метод делегата (после входа пользователя), вы можете проверить
navigationResponse.response
(брось этоNSHTTPURLResponse*
) и искатьSet-Cookie
Заголовок, который содержит информацию о сеансе, необходимую для аутентифицированных сеансов. - Затем вы можете загрузить CSV, указав вручную
Cookie
Заголовок в вашем запросе с файлами cookie, указанными в ответе.
Обратите внимание, что методы делегата вызываются только для запросов "основного кадра". Это означает, что запросы AJAX или внутренние кадры не будут запускать его. Вся страница должна обновиться, чтобы это работало.
Если вам нужно инициировать поведение для запросов AJAX, фреймов и т. Д., Вам нужно внедрить некоторый JavaScript.
Кажется, у меня нет файла cookie сеанса, когда я пытаюсь выполнить запрос от userContentController didReceiveScriptMessage.
Тем не менее, когда вызывается из definePolicyForNavigationAction, следующий код обнаруживает, что я вошел в систему.
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()