Il y a un fichier (CSV) que je souhaite télécharger. C'est derrière un écran de connexion sur un site Web. Je voulais afficher un WKWebView
pour permettre à l'utilisateur de se connecter, puis de demander à l'application de télécharger le fichier après s'être connecté.
J'ai essayé de télécharger le fichier en dehors de WKWebView
après que l'utilisateur s'est connecté au site Web, mais les données de session semblent être mises en sandbox car elles téléchargent un document html avec le formulaire de connexion au lieu du fichier souhaité.
J'ai également essayé d'ajouter un WKUserScript
à l'objet WKUserContentController
, mais le script ne s'exécute pas lorsqu'un fichier non HTML est chargé.
Existe-t-il un moyen pour moi d'accéder à ce fichier tout en permettant aux utilisateurs de se connecter via WKWebView
?
À l'heure actuelle, les instances WKWebView ignoreront les stockages réseau par défaut (NSURLCache, NSHTTPCookieStorage, NSCredentialStorage) ainsi que les classes de réseau standard que vous pouvez utiliser pour personnaliser les demandes réseau (NSURLProtocol, etc.).
Ainsi, les cookies de l'instance WKWebView ne sont pas stockés dans le stockage de cookies standard de votre application, et donc NSURLSession/NSURLConnection qui utilise uniquement le stockage de cookies standard n'a pas accès aux cookies de WKWebView (et c'est exactement le problème que vous avez probablement: le "statut de connexion" est probablement stocké dans un cookie, mais NSURLSession/NSURLConnection ne verra pas le cookie).
Il en va de même pour le cache, pour les informations d'identification, etc. WKWebView a ses propres stockages privés et ne fonctionne donc pas bien avec les classes de mise en réseau Cocoa standard.
Vous ne pouvez pas non plus personnaliser les demandes (ajouter vos propres en-têtes HTTP personnalisés, modifier les en-têtes existants, etc.), utiliser vos propres schémas d'URL personnalisés, etc., car NSURLProtocol n'est pas non plus pris en charge par WKWebView.
Donc, pour le moment, WKWebView est assez inutile pour de nombreuses applications, car il ne participe pas aux API de mise en réseau standard de Cocoa.
J'espère toujours que Apple changera cela jusqu'à la sortie d'iOS 8, car sinon WKWebView sera inutile pour de nombreuses applications, et nous resterons probablement avec UIWebView un peu plus longtemps.
Envoyez donc des rapports de bogues à Apple, donc Apple apprend que ces problèmes sont sérieux et doivent être corrigés.
Avez-vous vérifié les cookies de réponse revenant de la demande. Vous pouvez utiliser une méthode déléguée comme celle-ci.
- (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);
}
Vous pouvez obtenir le cookie via Javascript :
Vous pouvez ensuite utiliser le cookie obtenu pour télécharger le fichier manuellement:
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()
})
J'ai accompli quelque chose de similaire à ce que vous essayez de faire:
navigationDelegate
sur votre vue Web-webView:decidePolicyForNavigationResponse:decisionHandler
dans votre déléguénavigationResponse.response
(le convertir en NSHTTPURLResponse*
) et recherchez un Set-Cookie
en-tête contenant les informations de session dont vous aurez besoin pour les sessions authentifiées.Cookie
dans votre demande avec les cookies spécifiés dans la réponse.Notez que les méthodes déléguées sont uniquement appelées pour les requêtes "trame principale". Ce qui signifie que AJAX les requêtes ou les cadres internes ne le déclencheront pas. La page entière doit être actualisée pour que cela fonctionne.
Si vous devez déclencher un comportement pour les requêtes AJAX, iframes, etc., vous devrez injecter du javascript.
Je ne semble pas avoir le cookie de session lorsque j'essaie une demande de userContentController didReceiveScriptMessage.
Cependant, lorsqu'il est appelé à partir de decidePolicyForNavigationAction, le code suivant détecte que je suis connecté.
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()