简体   繁体   中英

How to load the html file with pdf on iOS WKWebView

In my project, I am using PDFJS library. I am loading a local pdf on UIWebView . But this occupies lot of RAM memory and at a point of time, its crashing. To avoid this, I want to use WKWebView .

In UIWebview , I am using like this ( self refers to subclass of UIView )

UIWebView *uiWebview = [[UIWebView alloc] initWithFrame:self.frame];
[self addSubview:uiWebview];
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"swift_tutorial" ofType:@"pdf"];
NSString *sPath = [[NSBundle mainBundle] pathForResource:@"viewer" ofType:@"html" inDirectory:@"PDFJS/web"];
NSString *finalPath = [NSString stringWithFormat:@"%@?file=%@#page=1",sPath,filePath];
self.urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:finalPath]];
[uiWebview loadRequest:self.urlRequest];

When I print finalPath in the above snippet, the console output is /var/containers/Bundle/Application/DF419672-CF14-4B60-BE4F-EC0AC07C23AE/WebviewPOC.app/PDFJS/web/viewer.html?file=/var/containers/Bundle/Application/DF419672-CF14-4B60-BE4F-EC0AC07C23AE/WebviewPOC.app/swift_tutorial.pdf#page=1

In WKWebView , loadFileURL , loadHTMLString methods can be used to load local html file or a local pdf file, which works fine. But not both. For this html file, how to append the local pdf path and load in the WKWebView ?

Any help appreciated.

Let me answer my own question.

I have used WKWebViewLocal library for creating a localhost server. Now, this will create access the local files via host name. Using this approach apps' memory utilization has been optimized a lot (Only because of WKWebView).

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"swift_tutorial" ofType:@"pdf"];    
NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"viewer" ofType:@"html" inDirectory:@"PDFJS/web"];
NSString *finalPath = [NSString stringWithFormat:@"http://localhost:8080%@?file=%@#page=1",htmlPath, filePath];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:finalPath]];
[self.webView loadRequest:request];

now, the finalpath will be

http://localhost:8080/~~~~~~~/PDFJS/web/viewer.html?file=/Users/~~~~~~/swift_tutorial.pdf#page=1

Because Apple will reject apps that use UIWebView API I had the same problem during moving from UIWebView to WKWebView. But since i'm using Xamarin framework i can't use WKWebViewLocal library. My solution is very similar.

First of all you need to add this code in OnElementChanged method in your CustomRenderer for WKWebView:

Control.Configuration.Preferences.SetValueForKey(NSObject.FromObject(true), new NSString("allowFileAccessFromFileURLs"));

It will grand access to files for this Control. Without it pdfjs won't be able to load documents and will always appear empty.

Then you need to change the code for reading files:

_pdfViewerAddress = (NSString)NSBundle.PathForResourceAbsolute("pdfjs/web/viewer", "html", NSBundle.MainBundle.ResourcePath);

if (UsePDFJS)
                {
                    var pdfjsUrlString = $"file://{_pdfViewerAddress}";
                    var pdfjsUrl = new NSUrl(pdfjsUrlString);

                    var docUrlString = $"file://{GetDocumentUrl()}";
                    var docFolderUrlString = new NSUrl($"file://{Element.PathWithoutFileName}");

                    var finalUrl = new NSUrl($"{pdfjsUrl}?file={docUrlString}#page=1");

                    Control.LoadFileUrl(finalUrl, docFolderUrlString);
                }
                else
                {
                    var error = new NSError();
                    var documentDirUrl = NSFileManager.DefaultManager.GetUrl(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User, null, false, out error);
                    var dotsFolderUrl = documentDirUrl.Append("..", true);
                    var libFolderUrl = dotsFolderUrl.Append("Library", true);
                    var tempFolderUrl = libFolderUrl.Append("TemporaryFiles", true);
                    var fileUrl = new NSUrl($"file://{GetDocumentUrl()}");

                    Control.LoadFileUrl(fileUrl, tempFolderUrl);
                }

In case of use pdfjs finalUrl should look like this:

file:///private/var/containers/Bundle/Application/80424409-E164-4409-A72B-43B32EC51F1A/iOS.app/pdfjs/web/viewer.html?file=file:///var/mobile/Containers/Data/Application/ED7233AE-8D10-41DC-8AF4-10662F14A883/Documents/../Library/TemporaryFiles/10850908.pdf#page=1

That's all. No external library needed. This also works if you want to open document from BundleResources. You can easily access it with this code:

(NSString)NSBundle.PathForResourceAbsolute("Guide", "pdf", NSBundle.MainBundle.ResourcePath);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM