Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

save a web view content as pdf file

Notice: I working with swift 4 for osx. I would like to generate a pdf file from a WebView.

At the moment my WebView load a html-string and show this successfully. If I press a button, the print panel will open and is ready to print my WebView content in the correct format.

This is my print code:

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

Now I would like to have another button, which save the content directly as a pdf file.

I tried this:

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)

But the result of my pdf looks horrible:

enter image description here

Have anybody an idea?

UPDATE This is a part of my web view result:

enter image description here

and that is the result of my print preview / pdf file /the color is missing, but now everywhere. the "logo"(picture) will show with color: enter image description here

like image 653
Ghost108 Avatar asked Sep 20 '17 18:09

Ghost108


1 Answers

The problem is that dataWithPDF uses the view's current frame to decide how wide the generated PDF should be. Since your WebView's frame in your app is probably skinnier than an 8.5/11" page, you're getting a PDF that is inadequately wide. You could adjust the WebView's frame to the right size, make the PDF, and then adjust it back, or you could create a new WebView, render it offscreen, set it to the appropriate size, and create the PDF. That's a bit of a pain in the backside, though. Wouldn't it be great if there were a way to programatically do what the "PDF" button in the Print dialog does, since the print system handles all this stuff for you automatically?

Well, turns out you can! But you have to dive into the poorly-documented world of 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()
}

The key is the PMSessionSetDestination call, which allows us to configure the print session to print to a PDF instead of to an actual printer. Then we just tell NSPrintOperation not to show the print panel, run the operation, and presto! PDF printed.

like image 175
Charles Srstka Avatar answered Oct 06 '22 00:10

Charles Srstka