将 WebView 保存为 PDF returns 空白图像?
Saving WebView to PDF returns blank image?
我正在尝试弄清楚如何将 WebView 保存为 PDF 并完全卡住,真的很感激一些帮助吗?
我在 Cocoa & Swift OSX 中执行此操作,这是我目前的代码:
import Cocoa
import WebKit
class ViewController: NSViewController {
override func loadView() {
super.loadView()
}
override func viewDidLoad() {
super.viewDidLoad()
loadHTMLString()
}
func loadHTMLString() {
let webView = WKWebView(frame: self.view.frame)
webView.loadHTMLString("<html><body><p>Hello, World!</p></body></html>", baseURL: nil)
self.view.addSubview(webView)
createPDFFromView(webView, saveToDocumentWithFileName: "test.pdf")
}
func createPDFFromView(view: NSView, saveToDocumentWithFileName fileName: String) {
let pdfData = view.dataWithPDFInsideRect(view.bounds)
if let documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {
let documentsFileName = documentDirectories + "/" + fileName
debugPrint(documentsFileName)
pdfData.writeToFile(documentsFileName, atomically: false)
}
}
}
这很简单,我正在做的是创建一个 WebView 并向其写入一些基本的 html 内容以呈现以下内容:
然后获取视图并将其保存为 PDF 文件,但结果为空白:
我试过从 webView 和 View 中抓取内容,但没有成功。
我在这里 How to take a screenshot when a webview finished rending 发现了一个关于将 webview 保存为图像的类似问题,但到目前为止 OSX 解决方案还没有成功。
会不会是跟文档尺寸有关?
或者内容在子视图中?
也许如果您捕获了视图,您就无法捕获子视图?
有什么想法吗?
所以我有点想出了解决方法,事实证明你不能(尤其是在 OSX 上)从 WKWebView 访问和打印 webview。
您必须使用 WebView 而不是 WKWebView(我最初是从 WKWebView 开始的,因为我读过的一些文章说要使用它)。
WebView 对象与 WKWebView 对象非常相似,这非常有趣:-)
但它可以让您访问 .mainFrame 和 .frameView,您需要打印它的内容。
这是我的代码:
let webView = WebView(frame: self.view.frame)
let localfilePath = NSBundle.mainBundle().URLForResource(fileName, withExtension: "html");
let req = NSURLRequest(URL: localfilePath!);
webView.mainFrame.loadRequest(req)
self.view.addSubview(webView)
呈现后,我添加了 1 秒的延迟,以确保内容在我打印之前已经呈现,
// needs 1 second delay
let delay = 1 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue()) {
// works!
let data = webView.dataWithPDFInsideRect(webView.frame)
let doc = PDFDocument.init(data: data)
doc.writeToFile("/Users/john/Desktop/test.pdf")
// works!
let printInfo = NSPrintInfo.sharedPrintInfo()
let printOperation = NSPrintOperation(view: webView.mainFrame.frameView, printInfo: printInfo)
printOperation.runOperation()
}
我在这里打印它并将其另存为 PDF,以确保它在所有情况下都能正常工作。
我确定它可以改进,我讨厌延迟 hack,应该在内容完全加载后用某种回调或委托 运行 替换它。
iOS 11.0 及更高版本,Apple 提供了以下API 来捕获 WKWebView 的快照。
@available(iOS 11.0, *)
open func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, completionHandler: @escaping (UIImage?, Error?) -> Swift.Void)
示例用法:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
if #available(iOS 11.0, *) {
webView.takeSnapshot(with: nil) { (image, error) in
//Do your stuff with image
}
}
}
iOS 10 及以下,必须使用 UIWebView 来捕获快照。可以使用以下方法来实现。
func webViewDidFinishLoad(_ webView: UIWebView) {
let image = captureScreen(webView: webView)
//Do your stuff with image
}
func captureScreen(webView: UIWebView) -> UIImage {
UIGraphicsBeginImageContext(webView.bounds.size)
webView.layer.render(in: UIGraphicsGetCurrentContext()!)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
这是另一个相关的
我正在尝试弄清楚如何将 WebView 保存为 PDF 并完全卡住,真的很感激一些帮助吗?
我在 Cocoa & Swift OSX 中执行此操作,这是我目前的代码:
import Cocoa
import WebKit
class ViewController: NSViewController {
override func loadView() {
super.loadView()
}
override func viewDidLoad() {
super.viewDidLoad()
loadHTMLString()
}
func loadHTMLString() {
let webView = WKWebView(frame: self.view.frame)
webView.loadHTMLString("<html><body><p>Hello, World!</p></body></html>", baseURL: nil)
self.view.addSubview(webView)
createPDFFromView(webView, saveToDocumentWithFileName: "test.pdf")
}
func createPDFFromView(view: NSView, saveToDocumentWithFileName fileName: String) {
let pdfData = view.dataWithPDFInsideRect(view.bounds)
if let documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {
let documentsFileName = documentDirectories + "/" + fileName
debugPrint(documentsFileName)
pdfData.writeToFile(documentsFileName, atomically: false)
}
}
}
这很简单,我正在做的是创建一个 WebView 并向其写入一些基本的 html 内容以呈现以下内容:
然后获取视图并将其保存为 PDF 文件,但结果为空白:
我试过从 webView 和 View 中抓取内容,但没有成功。
我在这里 How to take a screenshot when a webview finished rending 发现了一个关于将 webview 保存为图像的类似问题,但到目前为止 OSX 解决方案还没有成功。
会不会是跟文档尺寸有关? 或者内容在子视图中? 也许如果您捕获了视图,您就无法捕获子视图?
有什么想法吗?
所以我有点想出了解决方法,事实证明你不能(尤其是在 OSX 上)从 WKWebView 访问和打印 webview。
您必须使用 WebView 而不是 WKWebView(我最初是从 WKWebView 开始的,因为我读过的一些文章说要使用它)。
WebView 对象与 WKWebView 对象非常相似,这非常有趣:-)
但它可以让您访问 .mainFrame 和 .frameView,您需要打印它的内容。
这是我的代码:
let webView = WebView(frame: self.view.frame)
let localfilePath = NSBundle.mainBundle().URLForResource(fileName, withExtension: "html");
let req = NSURLRequest(URL: localfilePath!);
webView.mainFrame.loadRequest(req)
self.view.addSubview(webView)
呈现后,我添加了 1 秒的延迟,以确保内容在我打印之前已经呈现,
// needs 1 second delay
let delay = 1 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue()) {
// works!
let data = webView.dataWithPDFInsideRect(webView.frame)
let doc = PDFDocument.init(data: data)
doc.writeToFile("/Users/john/Desktop/test.pdf")
// works!
let printInfo = NSPrintInfo.sharedPrintInfo()
let printOperation = NSPrintOperation(view: webView.mainFrame.frameView, printInfo: printInfo)
printOperation.runOperation()
}
我在这里打印它并将其另存为 PDF,以确保它在所有情况下都能正常工作。
我确定它可以改进,我讨厌延迟 hack,应该在内容完全加载后用某种回调或委托 运行 替换它。
iOS 11.0 及更高版本,Apple 提供了以下API 来捕获 WKWebView 的快照。
@available(iOS 11.0, *)
open func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, completionHandler: @escaping (UIImage?, Error?) -> Swift.Void)
示例用法:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
if #available(iOS 11.0, *) {
webView.takeSnapshot(with: nil) { (image, error) in
//Do your stuff with image
}
}
}
iOS 10 及以下,必须使用 UIWebView 来捕获快照。可以使用以下方法来实现。
func webViewDidFinishLoad(_ webView: UIWebView) {
let image = captureScreen(webView: webView)
//Do your stuff with image
}
func captureScreen(webView: UIWebView) -> UIImage {
UIGraphicsBeginImageContext(webView.bounds.size)
webView.layer.render(in: UIGraphicsGetCurrentContext()!)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
这是另一个相关的