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

Posted

技术标签:

【中文标题】将 WebView 保存为 PDF 会返回空白图像?【英文标题】:Saving WebView to PDF returns blank image? 【发布时间】:2016-07-04 20:12:35 【问题描述】:

我正试图弄清楚如何将 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 内容来呈现:

然后获取视图并将其保存为 PDF 文件,但显示为空白:

我尝试从 webView 和 View 中获取内容,但没有任何乐趣。

我在这里How to take a screenshot when a webview finished rending 发现了一个关于将 webview 保存到图像的类似问题,但到目前为止,OSX 解决方案没有运气。

这可能与文档尺寸有关吗? 或者内容在子视图中? 也许如果您捕获视图,您就无法捕获子视图?

有什么想法吗?

【问题讨论】:

你好。如果您找到了问题的解决方案,请将其发布为答案,不要将其添加到您的问题中。另外请不要在标题中添加“已解决”。发布答案并将其标记为已接受是“解决”问题的方式。谢谢。 没问题 - 我已经恢复了您的编辑,您只需立即发布您的答案。谢谢! :) 完成,谢谢埃里克。唷,我很高兴我得到了这个工作,已经坚持了大约 2 周。 【参考方案1】:

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
    

这是另一个相关的answer

【讨论】:

【参考方案2】:

所以我想出了如何解决它,结果你不能(尤其是在 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,这样我就可以肯定它在所有情况下都能正常工作。

我确信它可以改进,我讨厌延迟黑客,应该用某种回调或委托替换它,以便在内容完全加载时运行。

【讨论】:

以上是关于将 WebView 保存为 PDF 会返回空白图像?的主要内容,如果未能解决你的问题,请参考以下文章

保存 matplotlib 表会产生大量空白

iOS:如何将 UIView 的自绘内容转换为图像(普遍的通用解决方案返回空白图像)?

在 webview 控件中显示本地 PDF 文件 - 显示空白 Pdf 文件

请问通过接口返回的pdf的文件流,怎么用php把这些文件流转为pdf文件

将 WebView 中的传入 PDF 保存到内存

Android - 如何将图片从 webview.capturePicture() 转换为 byte[] 并返回位图