Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to download a pdf from a authenticated session in wkwebview?

This question was asked before. But my requirement is different. I have a workflow like this

  1. User login to app using WKWebView()
  2. User has an invoice tab after logging in through which he can download invoices by clicking a button.
  3. The issue arises here. While desktop and android apps are able to download pdf , In iOS it's not downloading. I tried many workarounds like "decidePolicyFor", download pdf once its URL is known etc.
  4. The problem which I think is normal pdf files which needed to be downloaded usually has a ".pdf" at the end of its URL.. ex- "www.xyz.com/books.pdf", However mine is like this - "www.xyz.com/library/id=10"
  5. It may be also because the server give access to pdf only if it is authenticated. which is not the case if I try to download using URL directly

Any help will be appreciated

My CodeBase till now

import UIKit
import WebKit
class WebKitViewController: UIViewController {
    @IBOutlet weak var webView: WKWebView!
    var pdfUrl:URL!
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setViewContext()
    }

    func setViewContext()  {
        let url = URL(string: "https://www.example.com")!
        webView.navigationDelegate = self
        webView.load(URLRequest(url: url))
    }

    func downloadPDF(fromUrl url:String)  {
        guard let url = URL(string: url) else { return }

               let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())

               let downloadTask = urlSession.downloadTask(with: url)
               downloadTask.resume()

    }
    @IBAction func openPDFButtonPressed(_ sender: Any) {
        let pdfViewController = PDFViewController()
        pdfViewController.pdfURL = self.pdfUrl
        present(pdfViewController, animated: false, completion: nil)
    }}
extension WebKitViewController:WKNavigationDelegate{
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if let host = navigationAction.request.url {
            if host.absoluteString.contains("https://www.example.com/en/my-account/invoicePDF/"){
                 decisionHandler(.cancel)
                print(host.absoluteString)
                self.downloadPDF(fromUrl: host.absoluteString)
                return
            }
           }
           decisionHandler(.allow)

    }
}


extension WebKitViewController:  URLSessionDownloadDelegate {
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        print("downloadLocation:", location)
        do {
            let documentsURL = try
                FileManager.default.url(for: .documentDirectory,
                                        in: .userDomainMask,
                                        appropriateFor: nil,
                                        create: false)

            let savedURL = documentsURL.appendingPathComponent("yourCustomName90.pdf")
            self.pdfUrl = savedURL
            try FileManager.default.moveItem(at: location, to: savedURL)

        } catch {
            print ("file error: \(error)")
        }
    }
}

Note - The pdf downloads in macOS safari

like image 974
Jeesson_7 Avatar asked Jan 05 '20 05:01

Jeesson_7


People also ask

How do I download files from WKWebView?

With func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { , you get the file url to download. Then download it with JS.

How do I use WKWebView?

Here's how: Open the XIB or Storyboard you want to add the web view to in Interface Builder. Find the web view or WKWebView in the Object Library at the bottom-left of Interface Builder. Drag-and-drop a WKWebView object from the Object Library to your view controller's canvas, and adjust its size and position.

What is WKWebView?

Overview. A WKWebView object is a platform-native view that you use to incorporate web content seamlessly into your app's UI. A web view supports a full web-browsing experience, and presents HTML, CSS, and JavaScript content alongside your app's native views.


1 Answers

Try to read cookies from webview and save it before making a call to download your pdf:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    self.webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
       //save cookies
       self.cookies = cookies
    }
}


func downloadPDF(fromUrl url:String)  {
    guard let url = URL(string: url) else { return }
    HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL:nil)
    ...
}
like image 134
arturdev Avatar answered Sep 20 '22 03:09

arturdev