Detect if the content loaded in the web view is a PDF file and provide a downloadable option

I am using wkWebView to access research papers from IEEE, Science Direct, and other sources. When I click on a PDF in the research papers, it gets loaded into the webview. Is there a way to detect and enable a download icon in wkWebView?

Attempted Solution: I have used URLSession to retrieve PDFs from URLs, which works 95% of the time. However, sometimes the content is not fetched via URLSession due to dynamic URL/PDF creation, resulting in the PDF being loaded into the webview.

During my research, I found: Get already loaded PDF directly from WKWebView without downloading again. In my case, I first need to verify if the content loaded is a PDF.

A related query: add download button for pdf in wkwebview in swift 4, but unfortunately, there was no answer.

To test: open this URL: in wkWebView and click on the "Download PDF" button to load the PDF into the webview.

In essence: Is there a way to identify if the loaded content is a PDF and provide a download button to save the PDF content to the documents folder?

Any assistance would be greatly appreciated. Thank you.

Answer №1

To determine whether the content on the current page is a PDF, you can utilize the DOM Document.contentType API to check its mime/content type. If it returns application/pdf, it indicates that the web view is displaying a PDF, allowing you to display a download button accordingly:

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

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

checkIfCurrentDocumentIsPDF() {
    isPDF in

    if isPDF {
        pdfDownloadButton.isHidden = false
    }
}

Answer №2

After testing the link provided, I discovered that the download button opens the PDF in a new window using an HTML tag. However, the WKWebView seems to ignore this action.

To enable navigation, you will need to implement the WKUIDelegate protocol in your view controller and add 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 {
        // Load the request manually in the current window
        webView.load(navigationAction.request)
    }
    return nil
}

By implementing this code, the PDF will be loaded directly into the web view, allowing you to browse and download it like any other PDF file. If you need to download the PDF after it has loaded, you can use the Fetch API as explained here.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

npm build issues stemming from browserlist configurations

I am encountering an issue with my create-react-app failing to build, showing the following error: ./src/index.css Module build failed: BrowserslistError: Unknown browser query `dead` at Array.forEach (<anonymous>) I have carefully reviewed my ...

Beware: The use of anonymous arrow functions in Next.js can disrupt Fast Refresh and lead to the loss of local component state

I am currently encountering a warning that is indicating an anonymous object in a configuration file, and even specifying a name for it does not resolve the warning. Below you will find the detailed warning message along with examples. Warning: Anonymous ...

Ways to retrieve and upload a blob from a file object

After receiving a file object via an HTML input on-change event in my component.html: onFileSelected(event) { this.selectedFile = event.target.files[0]; } Now, I need to send a POST request to upload the image to the database. The database only acc ...

The complete height of the website is concealed by the mobile toolbar/menu

I encountered a perplexing issue regarding the responsive resizing of a website on mobile devices. The problem arises when the full height extends over the toolbar/menu, unless the user manually hides the toolbar. Is there a way to dynamically resize the ...

Creating a script to open multiple URLs in HTML and JavaScript

Currently, I am working on creating a multiple URL opener using HTML and JavaScript. However, I have encountered an issue where HTTP links are opening fine but HTTPS links are not. Can someone provide assistance with this problem? Below is the code snippet ...

Populate several input boxes with data derived from a single input field

I am facing an issue with three textboxes in my project. When I type something in the first textbox, the value is sent to state.jsp and displayed using out.println(firsttextboxvalue); on the response ID of the second textbox. However, I want to populate th ...

Properly managing mouseover events on a flipped div: tips and tricks

I created a div that flips when clicked using some HTML and CSS code. It works perfectly in Firefox 39 and Chrome 43. Here is the markup: <div class="flip-wrapper flippable-wrapper" id="fliptest-01"> <div class="flip-wrapper flippable ...

What is the best way to sort through this complex array of nested objects in Typescript/Angular?

tableData consists of an array containing PDO objects. Each PDO object may have zero or more advocacy (pdo_advocacies), and each advocacy can contain zero or more programs (pdo_programs). For example: // Array of PDO object [ { id: 1, ...

Unable to retrieve input using jquery selector

I am attempting to detect the click event on a checkbox. The Xpath for the element provided by firebug is as follows, starting with a table tag in my JSP (i.e. the table is within a div). /html/body/div[1]/div/div/div[2]/div/div[2]/div[1]/div/div[2]/table ...

Is it possible to asynchronously access a JSON object that has been retrieved from a local file on a global scale using the XMLHttpRequest method and

Having some trouble manipulating data from a local JSON file using this technique (no jQuery) as I can't seem to access the object on a global scale: var actual_JSON; function loadJSON(callback) { var xobj = new XMLHttpRequest(); xobj.o ...

ESLint is not performing linting even though the server is operational

I found a frontend template online and successfully installed all the packages using yarn. However, although I have an .eslint.json file in place and the ESLint extension is installed in Visual Studio Code, I am not seeing any linting errors. Below is the ...

Ways to determine the current page I am viewing

I am working with a list of tabs and I need to track my current location every time I click on a specific tab. My MainCTRL controller, which is the parent of all tab controllers, needs to be aware of the active tab at any given moment. I attempted to use n ...

Run the function once the page has completed downloading and bootstrapping

After experimenting with $evalAsync and $viewContentLoaded, I've found that they only trigger after Angular has completed populating the template. My goal is to determine, from within a directive: Is the template fully replaced by Angular? Have all ...

What is the method for determining the number of arrays contained within a file?

I am working with a JavaScript file that looks like this: // main.js let array1 = ['first array']; let array2 = ['second array']; Currently, I have two arrays declared in my main.js file. Is there a method to determine the total ...

Unveiling the Secrets of Encoding and Decoding JSON within a Concealed HTML

I am in the process of creating a unique control using HTML and JQuery that will showcase a specific text value. Users will have the ability to input various key/value pairs. Here is the current code snippet I am working with: <input id="keyValue" type ...

Navigating the route on express.js using two strings can be done by matching them effectively

I have a single route function that should match two different paths. The goal is to create profile pages for team members on a website, which can be accessed at www.domain.com/name. However, some team members prefer to use nicknames instead of their actua ...

Is it possible for a route's URL in ui-router to be at the same level as another state while also utilizing $stateParams?

In my application, I want to implement a feature where hitting the same level of the URL will lead to either the baz state or the biz state with a parameter. angular.module('foo') .config(function($stateProvider){ $stateProvider .state(&apos ...

The RefreshIndicator from Material-UI fails to display during the first page load

I am facing an issue with displaying a loading icon during the initial page load. The code appears to be correct to me but for some reason, the loading icon is not showing up. I am utilizing the RefreshIndicator component from material-ui for the loading i ...

How come my dimensions are not returning correctly when I use offset().top and scrollTop() inside a scrolling element?

Currently in the process of developing a web app at , I am looking to implement a feature that will fade elements in and out as they enter and leave the visible part of a scrolling parent element. Taking inspiration from myfunkyside's response on this ...

Modifying the URL path while navigating through pages with ajax and jQuery

I have implemented ajax post requests to enable paging on a feed within my website. Upon receiving the post request data, I refresh the page by clearing out previous content and displaying the new data retrieved from the request. In addition to this, I wan ...