swift - 将网页 View 内容保存为 pdf 文件

标签 swift macos cocoa pdf webview

注意:我使用 swift 4 for osx。 我想从 WebView 生成一个 pdf 文件。

此刻我的 WebView 加载了一个 html 字符串并成功显示了它。 如果我按下一个按钮,打印面板将打开并准备好以正确的格式打印我的 WebView 内容。

这是我的打印代码:

var webView = WebView()
var htmlString = "MY HTML STRING"

override func viewDidLoad() {
    webView.mainFrame.loadHTMLString(htmlString, baseURL: nil)
}

func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {

    let printInfo = NSPrintInfo.shared
    printInfo.paperSize = NSMakeSize(595.22, 841.85)
    printInfo.isHorizontallyCentered = true
    printInfo.isVerticallyCentered = true
    printInfo.orientation = .portrait
    printInfo.topMargin = 50
    printInfo.rightMargin = 0
    printInfo.bottomMargin = 50
    printInfo.leftMargin = 0
    printInfo.verticalPagination = .autoPagination
    printInfo.horizontalPagination = .fitPagination
    //webView.mainFrame.frameView.printOperation(with: printInfo).run()

    let printOp: NSPrintOperation = NSPrintOperation(view: webView.mainFrame.frameView.documentView, printInfo: printInfo)
    printOp.showsPrintPanel = true
    printOp.showsProgressPanel = false
    printOp.run() 
}

enter image description here

现在我想要另一个按钮,将内容直接保存为pdf文件。

我试过这个:

let pdfData = webView.mainFrame.frameView.documentView.dataWithPDF(inside: webView.mainFrame.frameView.documentView.frame)
let document = PDFDocument(data: pdfData)
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("myPDF.pdf")
document?.write(to: fileURL)

但是我的 pdf 的结果看起来很糟糕:

enter image description here

有人有想法吗?

更新 这是我的 WebView 结果的一部分:

enter image description here

那是我的打印预览/pdf 文件/颜色丢失的结果,但现在无处不在。 “标志”(图片)将显示颜色: enter image description here

最佳答案

问题是 dataWithPDF 使用 View 的当前框架来决定生成的 PDF 的宽度。由于您的应用程序中的 WebView 框架可能比 8.5/11"页面更窄,因此您得到的 PDF 宽度不够。您可以调整 WebView 的 frame 调整到合适的大小,制作 PDF,然后将其调整回来,或者您可以创建一个新的 WebView,将其渲染到屏幕外,将其设置为合适的大小,并创建 PDF。不过,这在后面有点麻烦。如果有一种方法可以以编程方式执行“打印”对话框中的“PDF”按钮所做的事情,那不是很好吗,因为打印系统会处理所有这东西自动给你?

好吧,事实证明你可以!但是您必须深入研究 Core Printing 的文档不足的世界。

func makePDF(at url: URL, for webView: WebView, printInfo: NSPrintInfo) throws {
    webView.preferences.shouldPrintBackgrounds = true

    guard let printOp = webView.mainFrame.frameView.printOperation(with: printInfo) else {
        throw MyPrintError.couldntGetPrintOperation // or something like this
    }

    let session = PMPrintSession(printOp.printInfo.pmPrintSession())
    let settings = PMPrintSettings(printOp.printInfo.pmPrintSettings())

    if PMSessionSetDestination(session,
                               settings,
                               PMDestinationType(kPMDestinationFile),
                               kPMDocumentFormatPDF as CFString,
                               url as CFURL) != noErr {
        throw MyPrintError.couldntSetDestination // or something like this
    }

    printOp.showsPrintPanel = false
    printOp.run()
}

关键是 PMSessionSetDestination 调用,它允许我们将打印 session 配置为打印到 PDF 而不是实际打印机。然后我们告诉 NSPrintOperation 不要显示打印面板,运行操作,然后就可以了! PDF 打印。

关于swift - 将网页 View 内容保存为 pdf 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46329586/

相关文章:

objective-c - 复选框状态问题

ios - Swift 中奇怪的保留周期

python - 如何在 mac os x (10.9) 上的 python 中安装 libgpuarray 和 clBLAS?

swift - MLMediaLibrary - 显示照片库 -Swift 代码错误 - macOS

c++ - Qt中有没有办法禁止计算机进入休眠状态?

Python pip 安装报错

objective-c - 如何从应用程序 B 访问应用程序 A 的功能

ios - malloc : nano zone abandoned due to inability to preallocate reserved vm space

swift - 在 Swift 3 中将 [UInt8] 转换为 [UInt32]

ios - 如何在没有 Storyboard的情况下添加 UItableview? (UITableView 错误)