简体   繁体   English

如何在 iOS WKWebView 上加载带有 pdf 的 html 文件

[英]How to load the html file with pdf on iOS WKWebView

In my project, I am using PDFJS library.在我的项目中,我使用的是PDFJS库。 I am loading a local pdf on UIWebView .我正在UIWebView上加载本地 pdf。 But this occupies lot of RAM memory and at a point of time, its crashing.但这会占用大量 RAM 内存,并且在某个时间点会崩溃。 To avoid this, I want to use WKWebView .为了避免这种情况,我想使用WKWebView

In UIWebview , I am using like this ( self refers to subclass of UIView )UIWebview ,我是这样使用的( self指的是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当我在上面的代码片段中打印 finalPath 时,控制台输出是/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.WKWebViewloadFileURLloadHTMLString方法可用于加载本地 html 文件或本地 pdf 文件,工作正常。 But not both.但不能两者兼而有之。 For this html file, how to append the local pdf path and load in the WKWebView ?对于这个 html 文件,如何附加本地 pdf 路径并加载到WKWebView

Any help appreciated.任何帮助表示赞赏。

Let me answer my own question.让我回答我自己的问题。

I have used WKWebViewLocal library for creating a localhost server.我使用WKWebViewLocal库来创建本地主机服务器。 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).使用这种方法应用程序的内存利用率已经优化了很多(仅因为 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.因为 Apple 会拒绝使用 UIWebView API 的应用程序,所以我在从 UIWebView 移动到 WKWebView 时遇到了同样的问题。 But since i'm using Xamarin framework i can't use WKWebViewLocal library.但由于我使用的是 Xamarin 框架,因此无法使用 WKWebViewLocal 库。 My solution is very similar.我的解决方案非常相似。

First of all you need to add this code in OnElementChanged method in your CustomRenderer for WKWebView:首先,您需要在 WKWebView 的 CustomRenderer 中的 OnElementChanged 方法中添加此代码:

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.没有它 pdfjs 将无法加载文档并且总是显示为空。

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:如果使用 pdfjs finalUrl 应该是这样的:

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.如果您想从 BundleResources 打开文档,这也适用。 You can easily access it with this code:您可以使用以下代码轻松访问它:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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