将WebView保存为PDF返回空白图像?

7

我正在尝试找出如何将WebView保存为PDF,但是完全卡住了,真的很需要帮助。

我在OSX上使用Cocoa和Swift进行此操作,以下是我的代码:

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内容,使其呈现如下效果:

这很简单。

View

然后将视图保存为PDF文件,但结果为空白:

PDF

我尝试了从webView和View中获取内容,但是没有成功。
我在这里找到了一个类似的问题 如何在webview完成渲染时截取屏幕 ,涉及将webview保存为图像,但目前还没有找到MacOS的解决方案。
可能与文档尺寸有关吗? 或者内容在子视图中? 也许如果你捕捉View,你就不能捕捉SubView?
有什么想法吗?

你好。如果你找到了解决方案,请将其作为答案发布,不要将其添加到问题中。同时,请不要在标题中添加“已解决”。发布答案并将其标记为已接受是“解决”问题的方法。谢谢。 - Eric Aya
没问题 - 我已经撤销了你的编辑,现在你只需要发布你的答案即可。谢谢! :) - Eric Aya
1
完成了,谢谢Eric。哎呀,我很高兴终于把它搞定了,卡在这上面已经有两个星期了。 - John Griffiths
2个回答

5

iOS 11.0及以上版本,苹果提供了以下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
    }

这里还有一篇相关的答案


3

我想我已经找到了解决方法,事实证明你不能(特别是在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)

渲染完成后,我添加了一秒钟的延迟,以确保内容已经渲染完毕再进行打印。

    // 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,应该用一些回调或委托来替换它,以便在内容完全加载后运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接