如何在 iOS WKWebView 上加载带有 pdf 的 html 文件
How to load the html file with pdf on iOS WKWebView
在我的项目中,我使用了 PDFJS
库。我正在 UIWebView
上加载本地 pdf。但这会占用大量 RAM 内存,并且在某个时间点会崩溃。为了避免这种情况,我想使用 WKWebView
。
在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];
当我在上面的代码片段中打印 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
在WKWebView
、loadFileURL
、loadHTMLString
中可以使用方法加载本地html文件或本地pdf文件,效果很好。但不是两者。对于这个 html 文件,如何附加本地 pdf 路径并加载到 WKWebView
?
感谢任何帮助。
让我回答我自己的问题。
我已经使用 WKWebViewLocal 库来创建本地主机服务器。
现在,这将创建通过主机名访问本地文件。使用这种方法,应用程序的内存利用率得到了很大优化(仅因为 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];
现在,最终路径将是
http://localhost:8080/~~~~~~~/PDFJS/web/viewer.html?file=/Users/~~~~~~/swift_tutorial.pdf#page=1
因为 Apple 会拒绝使用 UIWebView 的应用程序 API 我在从 UIWebView 迁移到 WKWebView 的过程中遇到了同样的问题。但是因为我使用的是 Xamarin 框架,所以我不能使用 WKWebViewLocal 库。我的解决方案非常相似。
首先,您需要在 WKWebView 的 CustomRenderer 的 OnElementChanged 方法中添加以下代码:
Control.Configuration.Preferences.SetValueForKey(NSObject.FromObject(true), new NSString("allowFileAccessFromFileURLs"));
它将授予此控件访问文件的权限。没有它 pdfjs 将无法加载文档并且总是显示为空。
那么需要修改读取文件的代码:
_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);
}
如果使用 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
就是这样。不需要外部库。如果您想从 BundleResources 打开文档,这也适用。您可以使用此代码轻松访问它:
(NSString)NSBundle.PathForResourceAbsolute("Guide", "pdf", NSBundle.MainBundle.ResourcePath);
在我的项目中,我使用了 PDFJS
库。我正在 UIWebView
上加载本地 pdf。但这会占用大量 RAM 内存,并且在某个时间点会崩溃。为了避免这种情况,我想使用 WKWebView
。
在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];
当我在上面的代码片段中打印 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
在WKWebView
、loadFileURL
、loadHTMLString
中可以使用方法加载本地html文件或本地pdf文件,效果很好。但不是两者。对于这个 html 文件,如何附加本地 pdf 路径并加载到 WKWebView
?
感谢任何帮助。
让我回答我自己的问题。
我已经使用 WKWebViewLocal 库来创建本地主机服务器。 现在,这将创建通过主机名访问本地文件。使用这种方法,应用程序的内存利用率得到了很大优化(仅因为 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];
现在,最终路径将是
http://localhost:8080/~~~~~~~/PDFJS/web/viewer.html?file=/Users/~~~~~~/swift_tutorial.pdf#page=1
因为 Apple 会拒绝使用 UIWebView 的应用程序 API 我在从 UIWebView 迁移到 WKWebView 的过程中遇到了同样的问题。但是因为我使用的是 Xamarin 框架,所以我不能使用 WKWebViewLocal 库。我的解决方案非常相似。
首先,您需要在 WKWebView 的 CustomRenderer 的 OnElementChanged 方法中添加以下代码:
Control.Configuration.Preferences.SetValueForKey(NSObject.FromObject(true), new NSString("allowFileAccessFromFileURLs"));
它将授予此控件访问文件的权限。没有它 pdfjs 将无法加载文档并且总是显示为空。
那么需要修改读取文件的代码:
_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);
}
如果使用 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
就是这样。不需要外部库。如果您想从 BundleResources 打开文档,这也适用。您可以使用此代码轻松访问它:
(NSString)NSBundle.PathForResourceAbsolute("Guide", "pdf", NSBundle.MainBundle.ResourcePath);