Je suis en train de migrer mon application d'UIWebView vers WKWebView. Tout se passe bien et fonctionne au fur et à mesure que je le bricole davantage. Cependant, je remarque maintenant que je ne peux pas télécharger les pièces jointes du forum.

J'utilise HCDownload et jusqu'à présent, cela a toujours fonctionné parfaitement pour moi, donc je sais que ce n'est pas à cette fin. Je crois que c'est la demande, mais je ne peux pas le comprendre.

Je sais ce qui suit:

UIWebView => WKWebView Equivalent
--------------------------------------------------------------
didFailLoadWithError => didFailNavigation
webViewDidFinishLoad => didFinishNavigation
webViewDidStartLoad => didStartProvisionalNavigation
shouldStartLoadWithRequest => decidePolicyForNavigationAction

Donc, avec cela connu, j'essaye ci-dessous:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    NSURLRequest *request = navigationAction.request;
    NSURL *fileURl = [request URL];
    NSString *externalFileExtension = [fileURl pathExtension];
    NSString *internalFileExtension = [[fileURl absoluteString] pathExtension];

    HCDownloadViewController *dlvc = [[HCDownloadViewController alloc] init];
    UINavigationController *vc = [[UINavigationController alloc] initWithRootViewController:dlvc];
    dlvc.delegate = self;
    vc.transitioningDelegate  = self;

    if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {

        //External file extensions
        if ([fileExtensions containsObject:[externalFileExtension lowercaseString]]) {
            [dlvc downloadURL:fileURl userInfo:nil];
            [self presentViewController:vc animated:YES completion:nil];
            [vc release];

            NSLog(@"externalURL is %@", fileURl);
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }

        //Internal file links
        if ([fileExtensions containsObject:[internalFileExtension lowercaseString]]) {
            [self presentViewController:vc animated:YES completion:nil];
            [dlvc downloadURL:fileURl userInfo:nil];
            [vc release];

            NSLog(@"internalURL is %@", fileURl);
            decisionHandler(WKNavigationActionPolicyCancel);
            return;

        }
}

Il lancera mon contrôleur de téléchargement en trouvant l'extension de fichier, mais à la place, il téléchargera le fichier index.php, pas le fichier.

Exemple d'URL:

https://example.com/index.php?app=core&module=attach&section=attach&attach_id=1234=example.zip;

Qu'est-ce que je fais mal. Cela fonctionnait bien avant dans UIWebView et je sais que les choses se font différemment. Mais comment peut-il télécharger quelque chose de disons dropbox très bien, mais un fichier joint sur un forum est gaffé.

Toute aide serait appréciée

4
ChrisOSX 31 déc. 2015 à 16:26

3 réponses

Meilleure réponse

Eh bien voici ce que j'ai fini avec, et tout semble bien fonctionner.

- (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);
    //NSLog(@"decidePolicyForNavigationResponse");
}


//Download manager
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    NSURLRequest *request = navigationAction.request;
    fileURL = request.URL;

    HCDownloadViewController *dlvc = [[HCDownloadViewController alloc] init];
    UINavigationController *vc = [[UINavigationController alloc] initWithRootViewController:dlvc];
    vc.transitioningDelegate  = self;
    dlvc.delegate = self;

    if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {

        //Internal file links
        NSString *internalFileExtension = fileURL.absoluteString.pathExtension;
        if ([fileExtensions containsObject:[internalFileExtension lowercaseString]]) {

            //Fire download
            [dlvc downloadURL:fileURL userInfo:nil];
            [self presentViewController:vc animated:YES completion:nil];
            [vc release];

            NSLog(@"internalURL is %@", fileURL);
            if (decisionHandler) {
                decisionHandler(WKNavigationActionPolicyCancel);
            }
            return;
        }

        //External file extensions
        NSString *externalFileExtension = fileURL.pathExtension;
        if ([fileExtensions containsObject:[externalFileExtension lowercaseString]]) {

            //Fire download
            [dlvc downloadURL:fileURL userInfo:nil];
            [self presentViewController:vc animated:YES completion:nil];
            [vc release];

            NSLog(@"externalURL is %@", fileURL);
            if (decisionHandler) {
                decisionHandler(WKNavigationActionPolicyCancel);
            }
            return;
        }
    }

    if (decisionHandler) {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}
6
ChrisOSX 12 janv. 2016 à 09:58

Vous téléchargez probablement une page non autorisée car vos instances WKWebView et HCDownload ne partagent pas de sessions de cookies comme le ferait UIWebView. C'est un compromis nécessaire pour les améliorations de vitesse et de sécurité du modèle de processus WK2.

J'ai ajouté le téléchargement à mon mini-navigateur OSX / Swift basé sur WKWebKit en implémentant _WKDownloadDelegate. C'est un protocole privé totalement non documenté depuis El Cap et iOS9. Il permet à votre délégué de navigation d'appeler decisionHandler(_WKNavigationResponsePolicyBecomeDownload) où WebKit se télécharge en arrière-plan après vous avoir donné la possibilité de choisir / modifier un nom de fichier. Je n'ai pas encore la moindre idée sur la façon d'implémenter un sélecteur de fichiers dans iOS, ni si l'utilisation de ce protocole serait autorisée par les critiques de l'App Store. Mais mon application gère désormais correctement le téléchargement à partir de sites d'authentification de session comme votre forum PHP.

4
kfix 5 janv. 2016 à 08:02

Swift 4:

La solution de ChrisOSX a également résolu mon problème. J'essaye de télécharger un document à partir d'un lien sur un site après m'être connecté à ce site. J'ai utilisé WKZombie pour gratter le lien, puis je voulais télécharger le fichier en utilisant Alamofire. J'ai ajouté ceci

if let httpResponse = navigationResponse.response as? HTTPURLResponse, let url = httpResponse.url {
    let allHeaders = httpResponse.allHeaderFields.reduce([String : String](), { (result, next) -> [String : String] in
    guard let stringKey = next.key as? String, let stringValue = next.value as? String else { return result }
        var buffer = result
        buffer[stringKey] = stringValue
        return buffer
    })
    let cookies = HTTPCookie.cookies(withResponseHeaderFields: allHeaders, for: url)
    for cookie in cookies {
        HTTPCookieStorage.shared.setCookie(cookie)
    }
}

À:

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void)

Après cela, les cookies sont stockés dans les cookies partagés et j'ai pu télécharger le fichier avec Alamofire sans modifier les méthodes de téléchargement.

1
Wiingaard 21 mars 2018 à 14:41