How to open a Link to a PDF with wkwebview - ios

I created a simple iOS app, which opens a URL with WKWebView. On the website, there is a link to a PDF Document. When I open the site on my browser, I can click onto the Link, and the PDF document opens. But on my App, nothing happens when I click onto the link.
How can I fix it? Do I have to put something into my info.plist?

SWIFT 3.* & 4.* *
First you have to download that pdf file into your app, after downloading you have to get that file path, then that file path should be use like following way in WKWebView.
let fileURL = URL(fileURLWithPath: filePathURLData as! String)
//print(fileURL)
webView.loadFileURL(fileURL, allowingReadAccessTo: fileURL)
Here filePathURLData is your actual file path which you have downloaded into your app, you have to convert this into URL, then you need to load that file into WKWebView
Thanks
Hope this will help you.
This will show any file in the WKWebView (doc, docx, xlsx, pdf, google doc, pages & Any textfile)

Likely, you are using target="_blank" in your anchor tag. That opens up a new window to display the link. WKWebView is blocking your attempt to open a new window (at least by default).
The code below still does not create a new window, but instead opens the PDF, etc link in the current WKWebView.
The other option seems to be to create a new WKWebView and return it, so the ios and open the link in that, but I don't want extra Views being created by every click on a website inside the WKWebView.
In your ViewController.viewDidLoad
webView.uiDelegate = self
Then add the extension for the delegate
extension ViewController: WKUIDelegate {
/**
* Force all popup windows to remain in the current WKWebView.
* By default, WKWebView is blocking new windows from being created
* ex text.
* This code catches those popup windows and displays them in the current WKWebView.
*/
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
// open in current view
webView.load(navigationAction.request)
// don't return a new view to build a popup into (the default behavior).
return nil;
}
}

I have same issue, and found out the pdf file is using unsecured http. Therefore the app refuse to open it.
Try to check with https link and see if it works.
Also with WKWebView, you don't need to download the pdf file before open it. Just load the url directly, i.e
webView.load(URLRequest(url: URL(string: "https-pdf-link")!))

Objective C:
NSURL *fileUrl = [[NSURL alloc] initWithString:filePathURLData];
[webView loadFileURL:fileUrl allowingReadAccessToURL:fileUrl];
Another way to open PDF saved in document directory:
NSData *data = [NSData dataWithContentsOfFile:fileURL];
[webView loadData:data MIMEType:#"application/pdf" characterEncodingName:#"" baseURL:[NSURL URLWithString:fileURL]];

Related

Setting local image on WKWebview using evaluateJavascript method

I have a HTML file which contains local resource files such as css, js files inside its content. These local resource files are in zip format. My app use WKWebView to display this html file. I m trying to upload an image in one of the html image element on WKWebview which is saved locally and html is not updated with the image. I have a html image tag in local html like this.
<img id='image' style='display: block; height: 100%; width:100%; margin:0 auto;' />
And this image to load in this image tag is generated after the local html file is loaded in the WKWebview. Once the image is generated, I am trying to update the image tag with the evaluate javascript method like this.
NSString *js = #"document.getElementById('image').src='document directory/Library/images/generatedImage.png';"
[self.wkWebView evaluateJavaScript:js completionHandler:nil];
Am I doing something wrong here. I also read that we can't update the image locally which was 2 years ago, still the same? Is there any workaround solution for my scenario. Thanks in advance.
I can think of two ways to do what you want.
Custom URL Scheme
Convert the image to base64 then set it via evaluate Javascript
Custom URL Scheme
This is supported from iOS Version 11, if you are supporting version below 11 then you are better off with second approach. The basic idea is mention your URL with custom protocol like my-scheme://your-path then intercept that path and provide the response to WKWebView. In this you have to create a class that extends WKSchemeHandler and override it's required methods. e.g.
import WebKit
import Foundation
class CustomeSchemeHandler : NSObject,WKURLSchemeHandler {
func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
}
func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
}
}
In the start method you can load the content from your desired source and then return the response via
urlSchemeTask.didReceive(response)
urlSchemeTask.didReceive(data)
urlSchemeTask.didFinish()
After implementing your logic, you need to register it with WKWebView via setURLSchemeHandler(_:forURLScheme:)
After seeing the above you can mention image URL with your custom scheme and leave the work to your CustomSchemeHandler.
This approach is very mature and can be really helpful in the long run. I found a very good and brief article that covers the implementation in details, do check it out: https://medium.com/#kumarreddy_b/custom-scheme-handling-in-uiwebview-wkwebview-bbeb2f3f6cc1
Convert the image to base64 then set it via evaluating Javascript
Create UIImage from your path e.g. https://stackoverflow.com/a/43006566/2299040
Convert the image to base64
Get the Id of your HTML image element and load the base64 String
e.g.
if let image = UIImage(contentsOfFile: ""){
//Now use image to create into NSData format
if let imageData = image.jpegData(compressionQuality: 0.8){
let strBase64 = imageData.base64EncodedString(options: .lineLength64Characters)
webView.evaluateJavaScript("document.getElementById('your-image-element-id').setAttribute('src', '\(strBase64)');")
}
}
For your example, I was able to load an image from the internet by setting that URL as the src.
I guess you might have not given read access to your local image file directory while loading the webview.
Utilize loadFileURL method of wkwebview to load an HTML file by giving access to a particular directory
For EG (in Swift),
let imgDir = "<your image directory>"
let imgDirUrl = URL(fileURLWithPath: String(format: "%#", imgDir), isDirectory: true)
webView.loadFileURL(<your HTML file URL path>, allowingReadAccessTo: imgDirUrl)
(In objc)
NSString *imgDir = "<your image directory>"
NSURL *imgDirUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#",imgDir] isDirectory:true];
[webView loadFileURL:<your HTML file URL path> allowingReadAccessToURL:imgDirUrl];

WKWebView Check if web view support to load a file

I am create a iOS Application. I am using WKWebView at some stage to show some files of any extension types. For Audio, Video, html, text, pdf, documents files its working well. But files like .zip , .csv and many others its not showing proper data or show blank screen without any error I am getting in its navigations delegates methods.
My Question is how can I check if my WKWebView is able to load/support that file? So that if it's not able to load or support that file, I can show another view where I will direct download that file to File manager and give user option to save or share that file.
Like In Safari browser when I am trying to load zip file its not show any preview , its show an alert to download (in iOS 13) or show Save and share file action (in iOS 13). How Safari is detecting that its support that file or not?
Please do not suggest to use direct String matching for mime types or extensions because there can be 1000+ files extensions in the world.
You need to make your controller as webView.navigationDelegate and define the navigation response delegate callback as follows:
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse,
decisionHandler: #escaping (WKNavigationResponsePolicy) -> Void) {
if navigationResponse.canShowMIMEType {
decisionHandler(.allow)
} else {
decisionHandler(.cancel)
// do something else with `navigationResponse.response`
}
}

How to display PDF URL file in app and it opens or views next page of PDF file like iBook

How to display PDF URL file in app and it opens or views next page of PDF file like iBook? I open the PDF URL on WebView but I'm not able to open the page like a book.
Try this one:
URL:
func loadFromUrl(){
let url = NSURL(string:"https://www.yourpdfFileUrl.pdf")
myWebView?.loadRequest(NSURLRequest(URL: url!))
}
Local:
func loadFromLocal()
{
let pdfPath = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("myPdfFile", ofType: "pdf")!)
myWebView?.loadRequest(NSURLRequest(URL: pdfPath))
}
Or
Follow this link
Opening .pdf in WebView will work but it will not have page curl effect like iBooks. For that you need to do this.
To achieve iBooks like effect you need to render pdf on view.
And you have to use UIPageViewController with curl animation.
If your using iOS 11.0 and onwards you can do it using newly available PDFKit.

iOS - Check if webView is loaded with PDF content on non-'pdf' file extension

I would like to Check (boolean value) if PDF content is loaded in the UIWebView. This question already exists, but not this case.
It's not as simple as just checking the path extension of the webView Url because this PDF content is generated via ASPX. The extension will return 'aspx'. Also not just looking in the url, the string 'pdf' will always be found in the url since I requesting a PDF file. I need to check if the server really returns a PDF file as it should.
Ok, The webView is loaded with PDF content but not to a specific pdf file on the server. (maybe apache redirect,aspx pdf generation or just something else)
If this url is loaded in the Safari Application (to the aspx file), it will detect this PDF content (even if aspx file). It says "open in..." and so on.
How to detect if the UIWebView is loaded with PDF content on non-pdf extention file?
Jonathan
I solved it using this:
Thanks #Guilherme
-(bool)isPDFContentLoadedInWebView:(UIWebView *)webView {
NSString *mime =[[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request].response.MIMEType;
if (!([mime rangeOfString:#"pdf"].location == 0)) {
return YES;
} else {
return NO;
}
return NO;
}

Open PDF link to PDF Reader in iOS

Am getting the PDF file link from my web view. when i click that link, i want to open that PDF file in my iBook application.
i got the contents from server. I showed that content in UIWebview like this.
In this content have a PDF link "Emerging Trends in Real Estate". When i choose this link, i want to open this pdf file in iPhone PDF reader applications like iBook, Adobe Reader. When i click this link it goes to webView Delegate method
-(BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL* url = [request URL];
NSLog(#"PDF URL : %#",url);
if (UIWebViewNavigationTypeLinkClicked == navigationType)
{
if ([url isEqual:#"about:blank"])
{
return YES;
}
else
{
// Initialize Document Interaction Controller
documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:url];
// Configure Document Interaction Controller
documentInteractionController.delegate = self;
// Present Open In Menu
[documentInteractionController presentOptionsMenuFromRect:CGRectZero inView:self.view animated:YES];
}
}
return YES;
}
when compiler comes to else part i got an error. i displayed that error :
PDF URL : http://www.uli.org/wp-content/uploads/ULI-Documents/Emerging-Trends-in-Real-Estate-Americas-2014.pdf
2014-01-17 16:44:49.233 ULINewYork[3163:a0b] *** Assertion failure in -[UIDocumentInteractionController setURL:], /SourceCache/UIKit_Sim/UIKit-2903.23/UIDocumentInteractionController.m:1010
2014-01-17 16:44:49.234 ULINewYork[3163:a0b] *** WebKit discarded an uncaught exception in the webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener: delegate: <NSInternalInconsistencyException> UIDocumentInteractionController: invalid scheme http. Only the file scheme is supported.
please give me some idea to handle this process.
I tried the same way you have used along with the help of apple documentation. I get the same error you mentioned, then I download the DocInteraction application for understanding the UIDocumentInteractionController In that application they use this class to open the files located in local app sandbox or the files located in the main bundle.
If your Intention is to make the user read the pdf file then leave the handling of request to the webview itself(take out the -webView: shouldStartLoadWithRequest: delegate method)
or else if you want to show some other options the ios device could do(print,preview,mail etc) with the file then you have to download that pdf file to local then set the url property of UIDocumentInteractionController object to the local path url you have saved the file before presenting.

Resources