Pdf Created from Html using UIViewPrintFormatter not showing local images - html

I am creating pdf from an html file with images.I tried creating from from Html as well as from UIWebView by loading the html in to web view .The following are the methods use for both approach
1.From html
func exportHTMLContentToPDF(HTMLContent: String) {
let printPageRenderer = CustomPrintPageRenderer()
let printFormatter = UIMarkupTextPrintFormatter(markupText: HTMLContent)
printPageRenderer.addPrintFormatter(printFormatter, startingAtPageAtIndex: 0)
let pdfData = drawPDFUsingPrintPageRenderer(printPageRenderer)
pdfData.writeToFile(pdfPath(), atomically: true)
}
2.From UiWebView by loading Html
func createPdfFromViewFormatter(viewFormatter:UIViewPrintFormatter) {
let printPageRenderer = CustomPrintPageRenderer()
printPageRenderer.addPrintFormatter(viewFormatter, startingAtPageAtIndex: 0)
let pdfData = drawPDFUsingPrintPageRenderer(printPageRenderer)
pdfData.writeToFile(pdfPath(), atomically: true)
}
Pdf creation method`
private func drawPDFUsingPrintPageRenderer(printPageRenderer: UIPrintPageRenderer) -> NSData! {
let data = NSMutableData()
UIGraphicsBeginPDFContextToData(data, CGRect(x: 0.0, y: 0.0, width: printPageRenderer.printableRect.width, height: printPageRenderer.printableRect.height), nil)
printPageRenderer.prepareForDrawingPages(NSRange(location: 0, length:printPageRenderer.numberOfPages() ))
for i in 0..<printPageRenderer.numberOfPages() {
UIGraphicsBeginPDFPage()
printPageRenderer.drawPageAtIndex(i, inRect: UIGraphicsGetPDFContextBounds())
}
UIGraphicsEndPDFContext()
return data
}
The issue is the image in the html is is not shown in the created pdf.But it is displayed while loading it in a UIWebView.

I'm having the same problem :
IOS Swift sharing PDF documents with images
I believe it's a bug. The only solution I found so far is to create a dummy UIWebView that I hide. I load the HTML in the UIWebView and then create the PDF. Here is my code :
override func viewDidLoad() {
super.viewDidLoad()
hiddenWebView.loadHTMLString(htmlText, baseURL: nil)
hiddenWebView.isHidden = true
}
override func viewDidAppear(_ animated: Bool) {
pdfDocument = getPdf()
let tmpDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
let fileURL = tmpDirectoryURL.appendingPathComponent("document.pdf")
pdfDocument.write(to: fileURL, atomically: false)
documentWebView.loadRequest(URLRequest(url: fileURL))
}
I hope it helps.

I faced same issue and finally I got the solution. Hope anyone help this solution. Just Replace createPdfFromViewFormatter methods 's code.
`
func createPdfFromViewFormatter(viewFormatter:UIViewPrintFormatter) {
// 2. Assign print formatter to UIPrintPageRenderer
let render = UIPrintPageRenderer()
render.addPrintFormatter(formatter, startingAtPageAt: 0)
// 3. Assign paperRect and printableRect
let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
let printable = page.insetBy(dx: 0, dy: 0)
render.setValue(NSValue(cgRect: page), forKey: "paperRect")
render.setValue(NSValue(cgRect: printable), forKey: "printableRect")
// 4. Create PDF context and draw
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
for i in 1...render.numberOfPages {
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
render.drawPage(at: i - 1, in: bounds)
}
UIGraphicsEndPDFContext()
// 5. Save PDF file
let path = "\(NSTemporaryDirectory())\(filename).pdf"
pdfData.write(toFile: path, atomically: true)
}
`
Call createPdfFromViewFormatter method Like That
let pdfData = createPdfFromViewFormatter(viewFormatter: webView!.viewPrintFormatter())

Related

How to insert signature image into PDF file in Swift?

I'm adding signature through a SwiftSignatureView and it give us UIImage. How can I add it in to PDF file? Here is my code,
func convertToPdfFileAndShare(){
let imageData = sigImage!.pngData() ?? nil
let base64String = imageData?.base64EncodedString() ?? ""
let fmt = UIMarkupTextPrintFormatter(markupText: " \(ShowPDFVC.condition)</h1><h1>Signature:</h1><p> </p><br></div><div><br><html><body><p></p><p><b><img src='data:image/png;base64,\(String(describing: base64String))'></b></p></body></html><br><br>")
"sigImage" is signature image.
you could try this approach to write your signature to a pdf file:
if let theImage = sigImage, let pdfPage = PDFPage(image: theImage) {
let doc = PDFDocument()
pdfPage.setBounds(CGRect(x: 0, y: 0, width: theImage.size.width, height: theImage.size.height), for: .mediaBox)
doc.insert(pdfPage, at: 0)
// write the pdf document to file
writeToFile(doc, file: "test")
}
func writeToFile(_ doc: PDFDocument, file: String) {
do {
let dir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileURL = dir.appendingPathComponent(file).appendingPathExtension("pdf")
doc.write(to: fileURL)
} catch {
print("\(error)")
}
}

Since iOS 14 creating a PDF from a Webview not working correctly

Before iOS 14 I had a function createPDF_Specs that created a DIN A4 PDF for me from a web view.
Since iOS14 however it moves the background picture of the webview (which is created from a htmlString) to a second site in the PDF. The strange thing is, that the webview is shown correctly.
The first picture shows how the web view is seen and the second one how the PDF ends up.
func createPDF_Specs(formatter: UIViewPrintFormatter, filename: String) -> String {
// From: https://gist.github.com/nyg/b8cd742250826cb1471f
// 2. Assign print formatter to UIPrintPageRenderer
let render = UIPrintPageRenderer()
render.addPrintFormatter(formatter, startingAtPageAt: 0)
// 3. Assign paperRect and printableRect
let page = CGRect(x: 0, y: 0, width: 841.8, height: 595.2) // A4, 72 dpi
let printable = page.insetBy(dx: -3, dy: -3)
render.setValue(NSValue(cgRect: page), forKey: "paperRect")
render.setValue(NSValue(cgRect: printable), forKey: "printableRect")
// 4. Create PDF context and draw
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, page, nil)
print(render.numberOfPages, "Number of pages")
for i in 1...render.numberOfPages {
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
print(bounds)
// render.drawPage(at: i - 1, in: bounds)
render.drawPage(at: i - 1, in: page)
}
UIGraphicsEndPDFContext()
// 5. Save PDF file
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let filePath = "\(documentsPath)/\(filename).pdf"
pdfPath = URL(string: filePath)
pdfData.write(toFile: filePath, atomically: true)
print("open \(filePath)")
return filePath
}
Answer: This was an apple bug. I reported it to Apple and they fixed it with iOS 14.1

How to display links and images from an HTML String

I have a string that contains HTML code. What is the best way to display that (it contains images), also I want to make links in that tappable (open in Safari)
I have tried String extension that gives me NSAttributedString from HTML, but the image is only partially shown and links are not tappable.
let text = htmlString.attributedString(withRegularFont: UIFont.systemFont(ofSize: 14), andBoldFont: UIFont.systemFont(ofSize: 16))
extension String {
func attributedString(withRegularFont regularFont: UIFont, andBoldFont boldFont: UIFont, textColor: UIColor = UIColor.gray) -> NSMutableAttributedString {
var attributedString = NSMutableAttributedString()
guard let data = self.data(using: .utf8) else { return NSMutableAttributedString() }
do {
attributedString = try NSMutableAttributedString(data: data,
options: [.documentType: NSAttributedString.DocumentType.html,
.characterEncoding:String.Encoding.utf8.rawValue],
documentAttributes: nil)
let range = NSRange(location: 0, length: attributedString.length)
attributedString.enumerateAttribute(NSAttributedString.Key.font, in: range, options: .longestEffectiveRangeNotRequired) { value, range, _ in
let currentFont: UIFont = value as! UIFont
var replacementFont: UIFont? = nil
if currentFont.fontName.contains("bold") || currentFont.fontName.contains("Semibold") {
replacementFont = boldFont
} else {
replacementFont = regularFont
}
let replacementAttribute = [NSAttributedString.Key.font:replacementFont!, NSAttributedString.Key.foregroundColor: textColor]
attributedString.addAttributes(replacementAttribute, range: range)
} catch let e {
print(e.localizedDescription)
}
return attributedString
}
}
It shows me the HTML inside the UILabel but I am not able to tap on links and images are cropped respective to device width.
I think that the best option is to save this html string as a file and then load this file using web view.
check this question

Not able to convert html code to pdf

I have an html template. I want to convert it into a pdf and share.
When I do something like so...
let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: [self.appDelegate.HTMLContent], applicationActivities: nil)
self.present(activityViewController, animated: true, completion: nil)
Then what is shared is just the html code. I wanted to convert the html code to pdf and then share it. What am I to do for it...?
Use following method to convert your HTML string to PDF data format of A4 size:
func generatePDF(from html: String) -> NSData {
let fmt = UIMarkupTextPrintFormatter(markupText: html)
// 2. Assign print formatter to UIPrintPageRenderer
let render = UIPrintPageRenderer()
render.addPrintFormatter(fmt, startingAtPageAt: 0)
// 3. Assign paperRect and printableRect
let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
let printableRect = CGRect(x: 47.6, y: 70.9, width: 500, height: 700) // Adding margin to page
render.setValue(page, forKey: "paperRect")
render.setValue(printableRect, forKey: "printableRect")
// 4. Create PDF context and draw
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)
for i in 0..<render.numberOfPages {
UIGraphicsBeginPDFPage()
render.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
}
UIGraphicsEndPDFContext()
return pdfData
}
Now use the following code to share it:
let pdfData = generatePDF(from: self.appDelegate.HTMLContent)
let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: [pdfData], applicationActivities: nil)
self.present(activityViewController, animated: true, completion: nil)

How to create PDF in Swift

I want to create a PDF using UIWebView. As I have any work sheet details and I want to save generate PDF in Swift. I'm using HTML format with tables but in second page my border is cutting.
For Swift 2 I used to use
html string (is the exact html code used for your table) as String!
Then
let render = UIPrintPageRenderer()
let fmt = UIMarkupTextPrintFormatter(markupText: html)
render.addPrintFormatter(fmt, startingAtPageAtIndex: 0)
// 3. Assign paperRect and printableRect
let page = CGRect(x: 0, y: 0, width: 612, height: 792) // some defaults
let printable = page.insetBy(dx: 0, dy: 0)
render.setValue(NSValue(CGRect: page), forKey: "paperRect")
render.setValue(NSValue(CGRect: printable), forKey: "printableRect")
// 4. Create PDF context and draw
//let pointzero = CGPoint(x: 0,y :0)
let rect = CGRect.zero
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)
for i in 0..<render.numberOfPages {
UIGraphicsBeginPDFPage();
render.drawPageAtIndex( i, inRect: UIGraphicsGetPDFContextBounds())
}
UIGraphicsEndPDFContext();
// 5. Save PDF file
let path = "\(NSTemporaryDirectory())sd.pdf"
pdfData.writeToFile( path, atomically: true)
print("open \(path)")