3

I am using wkWebView to load research papers published on IEEE, Science Direct, etc. so when I click on any PDF in the research papers, PDF gets loaded into webview, so is there a way to detect and enable a download icon in wkWebView.

Tried Solution: I have tried to get the pdf from URLs via URLSession and this is working for like 95% of the times but sometimes I don't get the content of PDF via URLSession and pdf gets loaded into webview because of dynamic URL/PDF creation.

In research, I came across: Get already loaded PDF directly from WKWebView without downloading again But in my case first I need to check if the loaded content is PDF.

A relevant question: add download button for pdf in wkwebview in swift 4 But no answer!!!

To test: open URL: https://www.sciencedirect.com/science/article/pii/S0946672X17308763 in wkWebView and click on the "Download PDF" button this will load the pdf into webview.

In short: Any way to detect if the loaded content is PDF and give a download button to download the pdf content into the documents folder.

Any help appreciated...Thanks

Mohit Kumar
  • 2,898
  • 3
  • 21
  • 34
  • At the link you give, I have to click first Download, then Download this Article (this takes me to their PDF reader, rather than having `WKWebView` try to display the PDF) then Download again, after which the PDF is finally loaded into the `WKWebView`. Is this the correct set of steps to reproduce what you're talking about? – mattsven Feb 17 '20 at 15:54
  • you can follow any steps..the point is when pdf loaded into webview we need some javascript code or so to detect if the webview contains PDF and save that pdf to documents. Now, why javascript? because there are a lot of URLs that don't have any pdf as part of URL or so. Please let me know if you need any more clarification. – Mohit Kumar Feb 17 '20 at 16:25
  • Seems from other comments OP has made that other factors are involved other than just a simple web page displaying a PDF – Jesse Schokker Feb 23 '20 at 11:40

2 Answers2

2

You can detect if the content of the current page is a PDF by checking its mime/content type via the DOM Document.contentType API. If it's application/pdf, we know the web view is currently displaying a PDF, and can show a download button:

func isCurrentDocumentPDF(_ onCompletion: (Bool) -> Void) {
    webView.evaluateJavascript("document.contentType") {
        _, result in

        if let contentType = result as? String, contentType == "application/pdf" {
            onCompletion(true)
        } else {
            onCompletion(false)
        }
    }
}

isCurrentDocumentPDF() {
    isPDF in

    if isPDF {
        pdfDownloadButton.isHidden = false
    }
}
mattsven
  • 22,305
  • 11
  • 68
  • 104
  • I got error in return: Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=0, WKJavaScriptExceptionMessage=, WKJavaScriptExceptionColumnNumber=0, NSLocalizedDescription=A JavaScript exception occurred} – Mohit Kumar Feb 18 '20 at 17:42
  • Some things to check: 1. make sure the page is fully loaded first 2. with the PDF loaded on your device/simulator, try evaluating `document.contentType` from Safari's debugger and see if you get the same error: https://itnext.io/customizing-wkwebview-in-ios-523d85c115f#64a3 – mattsven Feb 18 '20 at 19:21
  • Error in console: Blocked script execution in 'myurl' because the document's frame is sandboxed and the 'allow-scripts' permission is not set. How can we set this permission in wkWebView? – Mohit Kumar Feb 18 '20 at 19:39
  • Can you link me to the page/document you're testing? – mattsven Feb 18 '20 at 20:03
  • It sounds like an `iframe` is involved, which there shouldn't be if the PDF is being loaded directly into the web view as the top-level document (rather than being embedded in a page). – mattsven Feb 18 '20 at 20:11
  • I understand your problem here but the content is restricted and I am thinking of ways to give you access to that content. – Mohit Kumar Feb 19 '20 at 12:29
  • If you can't give me access to the page itself, you may want to try to find a page that behaves similarly (gives the same error.) – mattsven Feb 19 '20 at 17:20
1

I've tried the link you've provided and it seems like the download button opens PDF in a new window (html tag ) and WKWebView just ignores it.

To make navigation possible you should adopt WKUIDelegate protocol in your view controller and implement a delegate method:

override func viewDidLoad() {
   super.viewDidLoad()     
   self.webView.uiDelegate = self
}

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if navigationAction.targetFrame == nil {
        // Here we load this request manually in current window
        webView.load(navigationAction.request)
    }
    return nil
}

In this example the PDF will be loaded directly into web view and you can browse/download it as you do for usual PDF files. If you then need to download that PDF (after it is loaded) you need to use a Fetch API as described here.

Roman F
  • 135
  • 2
  • 7
  • please read the question...I need a way to check if the loaded content in webview is pdf and download that particular pdf. And the fetch API that you have mentioned above if you check that is for very specific "id" and in my case, this is not possible. Please update your answer if you have a solution for this. – Mohit Kumar Feb 17 '20 at 07:02