iOS: open webview pdf in browser OR download pdf

1

I'm working on an iOS application with Swift. It works perfectly, however when I click on the pdf download link, it just displays the pdf. I wanted it to downdload OR open the pdf in the browser outside the webview. Anyone who has a solution will be grateful, as I have spent some time trying to resolve this. In some surveys I saw a staff commenting on configuring the Delegate, but how is this configuration? Does it need to be done?

import UIKit

class ViewController: UIViewController {
  @IBOutlet weak
  var myWebView: UIWebView!

    override func viewDidLoad() {
      super.viewDidLoad()

      let url = URL(string: "http://site/")
      let urlRequest = URLRequest(url: url!)
      myWebView.loadRequest(urlRequest)
 

 //Eu tentei fazer isso, mas ele abre o pdf no browser quando abro o aplicativo, sendo que a ideia é abrir o pdf só qnd eu clicar no link. Um link que gera um boleto 

if let url = URL(string: "https://prod-bepay-boletos.s3-us-west-2.amazonaws.com/boleto-A96C9542-79F4-9A8F-E2F1-F26120DABC45.pdf") {
  UIApplication.shared.open(url)
  }
 }
}
    
asked by anonymous 08.08.2018 / 20:24

2 answers

0

What you really need is to monitor the user's navigation. You can do this in UIWebView too but UIWebView is deprecated so I recommend using WKWebView for this:

import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
    let webView = WKWebView()
    override func viewDidLoad() {
        super.viewDidLoad()
        print("Documents\n", FileManager.documents)
        let url = URL(string: "https://www.google.com")!
        webView.frame = view.bounds
        webView.navigationDelegate = self
        webView.load(URLRequest(url: url))
        webView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
        view.addSubview(webView)
    }
}

extension FileManager {
    static let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
}

And implement the func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) method to detect when the user clicks a link and if that link is a pdf:

extension ViewController {
    public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if navigationAction.navigationType == .linkActivated  {
            if let url = navigationAction.request.url,
                url.pathExtension == "pdf" {
                print("pdf url:\n", url, "\nNo need to open locally")
                decisionHandler(.cancel)

                // se voce quiser pode download o pdf
                URLSession.shared.downloadTask(with: url) { location, response, error in
                    guard let location = location, let response = response else {
                        print("error:", error ?? "nil")
                        return
                    }
                    print("Location:", location.path, "\nResponse:", response, "\nFilename:", response.suggestedFilename ?? "file.pdf")
                    do {
                        let destination = FileManager.documents.appendingPathComponent(response.suggestedFilename ?? "file.pdf")
                        print("destination:", destination.path)
                        try FileManager.default.moveItem(at: location,  to: destination)
                        print("file moved from temporary location to documents directory")
                    } catch {
                        print("File copy/move error:", error)
                    }
                }.resume()
                // ou exibir usando o safari
                // if UIApplication.shared.canOpenURL(url) {
                //    UIApplication.shared.open(url)
                //     print(url)
                //    print("abrindo pdf com default browser")
                // }
                //
            } else {
                print("user clicked on a link that it is not a pdf")
                decisionHandler(.allow)
            }
        } else {
            decisionHandler(.allow)
        }
    }
}
    
09.08.2018 / 19:04
0

Here's a sketch of the solution to your problem. The downloadPDF method downloads the file and saves it to the device, using the FileDownloader class. The PDF will be saved inside the Documents folder.

The displayPDF method uses UIDocumentInteractionController to find applications that can display the file.

class ViewController: UIViewController, UIDocumentInteractionControllerDelegate {

    func pdfFileURL() -> URL {
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let pdfFileURL = documentsURL.appendingPathComponent("file.pdf")
        return pdfFileURL
    }

    func downloadPDF() {
        let url = URL(string: "https://www.server.com/file.pdf")
        FileDownloader.load(url: url!, to: self.pdfFileURL(), completion: { (success) in
            print("Download succeeded? \(success)")
        })
    }

    func displayPDF() {
        let fileURL = self.pdfFileURL()
        if (!FileManager.default.fileExists(atPath: fileURL.path)) {
            print("File not found")
            return
        }
        let documentController = UIDocumentInteractionController.init(url: fileURL)
        documentController.delegate = self
        documentController.presentPreview(animated: true)
    }

    //MARK: UIDocumentInteractionControllerDelegate
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        return self
    }
}

class FileDownloader {
    class func load(url: URL, to destination: URL, completion: @escaping (Bool) -> ()) {
        let task = URLSession.shared.downloadTask(with: url) { localURL, urlResponse, error in

            if let error = error {
                print("Error downloading file: %@", error.localizedDescription);
                completion(false)
                return
            }

            if let urlResponse = urlResponse as? HTTPURLResponse, urlResponse.statusCode == 200 {
                if let localURL = localURL {
                    do {
                        try FileManager.default.copyItem(at: localURL, to: destination)
                        completion(true)
                        return
                    } catch (let writeError) {
                        print("Error writing file to \(destination) : \(writeError)")
                    }
                }
            } else {
                print("Server returned an error")
            }

            completion(false)
        }
        task.resume()
    }
}
    
09.08.2018 / 01:43