Friday, September 29, 2017

save a web view content as pdf file

Leave a Comment

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

1 Answers

Answers 1

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.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment