How to image write in pdf through html in Swift 4 - ios

How to image write in pdf through html in Swift 4?
func createPDF(html: String, formmatter: UIViewPrintFormatter, filename: String) -> String
{
let fmt = UIMarkupTextPrintFormatter(markupText: sampleHTML)
// 2. Assign print formatter to UIPrintPageRenderer
let render = UIPrintPageRenderer()
render.addPrintFormatter(fmt, startingAtPageAt: 0)
render.drawPrintFormatter(formmatter, forPageAt: 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
UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
UIGraphicsBeginImageContext(CGSize.zero)
for i in 1...render.numberOfPages
{
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
render.drawPage(at: i - 1, in: bounds)
}
UIGraphicsEndPDFContext();
// 5. Save PDF file
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
print(documentsPath)
if pdfData.write(toFile: "\(documentsPath)/file.pdf", atomically: true)
{
pdfFilePath = "\(documentsPath)/file.pdf"
var URL = NSURL(fileURLWithPath: pdfFilePath!)
storedPdfFileData = try! Data(contentsOf:URL as URL)
fileName = URL.lastPathComponent
print("FileName\(fileName!)")
self.UserDefaultForfileName.setValue(self.fileName, forKey: "FILE")
}
else
{
print("choose how to handle error here")
}
return pdfFilePath!
}

If we have correctly understood, we can see two different requirements from your comments
1) you want to save the html pages to pdf.
or
2) you want to create pdf from images (list of UIImage).
for 1st approach:-
You should be using WKWebView to show html pages in your viewController. ( To know how to use WKWebView, you may search help from Stackoverflow. ) In the viewControler, you can have Button click event for 'printWebPagetoPDF" function. The function is as under.
func printWebPagetoPDF( theHeight:CGFloat = 0 ) {
var isHeightFound = true
let deviceW = UIScreen.main.bounds.size.width
let deviceH = UIScreen.main.bounds.size.height
let width = min(deviceW, deviceH)
var height = theHeight
if height <= 0 {
height = max(deviceW, deviceH)
isHeightFound = false
}
let fileParentPath = "<absolute path to save pdf file>" + "/"
let inDateTimeFormatter = DateFormatter()
inDateTimeFormatter.dateFormat = "yyyyMMddHHmm"
let dateTimeFileString = "test\(inDateTimeFormatter.string(from: Date()))"
let pdfFileName = dateTimeFileString + ".pdf"
let sharePdfFilePath = fileParentPath + pdfFileName
// - 1 - Grab the webView's print context
let fmt = myWKWebView.viewPrintFormatter()
fmt.perPageContentInsets = UIEdgeInsetsMake(10, 10, 10, 10) //Page margins
// - 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: width, height: height) //width: 841.85, height: 595.22) //Page size
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, page, nil)
print( render.numberOfPages )
render.prepare(forDrawingPages: NSMakeRange(0, render.numberOfPages-1))
for i in 0..<render.numberOfPages {
UIGraphicsBeginPDFPage()
render.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
}
UIGraphicsEndPDFContext()
// - 5 - Save the PDF file
let path = sharePdfFilePath
pdfData.write(toFile: path, atomically: true)
}
for 2nd approach:-
You may try following code to create pdf from images. I have not tested it properly, but you can try yourselves. mySelectedArray is the sequence of indexes of images to add in pdf. dataArray is array of UIImages. "import PDFKit" is required on start of swift file.
// The url to save the data to
let pdfFileName = "<some path>" + "/" + "test.pdf"
let url = URL(fileURLWithPath: pdfFileName)
if #available(iOS 11.0, *) {
// Create an empty PDF document
let pdfDocument = PDFDocument()
pdfDocument.delegate = self
for index in mySelectedArray {
// Load or create your UIImage
let image = dataArray[index].image
// Create a PDF page instance from your image
let pdfPage = PDFPage(image: image)
// Insert the PDF page into your document
pdfDocument.insert(pdfPage!, at: 0)
}
// Get the raw data of your PDF document
let data = pdfDocument.dataRepresentation()
// Save the data to the url
try! data!.write(to: url)
}
If possible, please comment clearly, for any further assistance.

Related

how to add create pdf button at share sheet IOS in swift 5

I open url using uiwebview then I show share sheet, but there is no create pdf button. I want show the create pdf button like safari, and create pdf from url then share the pdf. how to do it?
OR how to create pdf from url webview/uiview then save pdf to files?
this is my share sheet
and this is safari share sheet have create pdf button
and this my code to show share sheet
let items = [URL(string: "https://www.apple.com")!]
let ac = UIActivityViewController(activityItems: items, applicationActivities: nil)
present(ac, animated: true)
extension WKWebView {
// Call this function when WKWebView finish loading
func exportAsPdfFromWebView() -> String {
let pdfData = createPdfFile(printFormatter: self.viewPrintFormatter())
return self.saveWebViewPdf(data: pdfData)
}
func createPdfFile(printFormatter: UIViewPrintFormatter) -> NSMutableData {
let originalBounds = self.bounds
self.bounds = CGRect(x: originalBounds.origin.x,
y: bounds.origin.y,
width: self.bounds.size.width,
height: self.scrollView.contentSize.height)
let pdfPageFrame = CGRect(x: 0, y: 0, width: self.bounds.size.width,
height: self.scrollView.contentSize.height)
let printPageRenderer = UIPrintPageRenderer()
printPageRenderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)
printPageRenderer.setValue(NSValue(cgRect: UIScreen.main.bounds), forKey: "paperRect")
printPageRenderer.setValue(NSValue(cgRect: pdfPageFrame), forKey: "printableRect")
self.bounds = originalBounds
return printPageRenderer.generatePdfData()
}
// Save pdf file in document directory
func saveWebViewPdf(data: NSMutableData) -> String {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let docDirectoryPath = paths[0]
let pdfPath = docDirectoryPath.appendingPathComponent("webViewPdf.pdf")
if data.write(to: pdfPath, atomically: true) {
return pdfPath.path
} else {
return ""
}
}
}
extension UIPrintPageRenderer {
func generatePdfData() -> NSMutableData {
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, self.paperRect, nil)
self.prepare(forDrawingPages: NSMakeRange(0, self.numberOfPages))
let printRect = UIGraphicsGetPDFContextBounds()
for pdfPage in 0..<self.numberOfPages {
UIGraphicsBeginPDFPage()
self.drawPage(at: pdfPage, in: printRect)
}
UIGraphicsEndPDFContext();
return pdfData
}
}
You can create pdf from url webview/uiview then save pdf to files using this
I found the answer from other
first I create new class PDF.swift
class func generate(using printFormatter: UIPrintFormatter) -> String {
// assign the print formatter to the print page renderer
let renderer = UIPrintPageRenderer()
renderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)
// static let ANSI_A = CGSize(width:612,height:792)
// static let ANSI_B = CGSize(width:792,height:1224)
// static let ANSI_C = CGSize(width:1584,height:1224)
// static let ANSI_D = CGSize(width:2448,height:1584)
// static let ANSI_E = CGSize(width:3168,height:2448)
//
// static let ISO216_A0 = CGSize(width:2384,height:3370)
// static let ISO216_A1 = CGSize(width:1684,height:2384)
// static let ISO216_A2 = CGSize(width:1190,height:1684)
// static let ISO216_A3 = CGSize(width:842,height:1190)
// static let ISO216_A4 = CGSize(width:595,height:842)
// static let ISO216_A5 = CGSize(width:420,height:595)
// static let ISO216_A6 = CGSize(width:298,height:420)
// static let ISO216_A7 = CGSize(width:210,height:298)
// static let ISO216_A8 = CGSize(width:148,height:210)
// assign paperRect and printableRect values
let page = CGRect(x: 0, y: 0, width: 1190, height: 842) // A3 landscape
// let page = CGRect(x: 0, y: 0, width: 2384, height: 800) // A4, 72 dpi
renderer.setValue(page, forKey: "paperRect")
renderer.setValue(page, forKey: "printableRect")
// create pdf context and draw each page
let pdfData = NSMutableData()
// UIGraphicsBeginPDFContextToData(pdfData, .zero, nil)
UIGraphicsBeginPDFContextToData(pdfData, page, nil)
for i in 0..<renderer.numberOfPages {
UIGraphicsBeginPDFPage()
renderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
}
UIGraphicsEndPDFContext();
// save data to a pdf file and return
guard nil != (try? pdfData.write(to: outputURL, options: .atomic))
else { fatalError("Error writing PDF data to file.") }
return outputURL.absoluteString
}
private class var outputURL: URL {
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
else { fatalError("Error getting user's document directory.") }
let url = directory.appendingPathComponent(outputFileName).appendingPathExtension("pdf")
print("open \(url.path)")
return url
}
private class var outputFileName: String {
return "generated-\(Int(Date().timeIntervalSince1970))"
}
and call the function to generate pdf then share using share sheet to save files
let uiPDFData = PDF.generate(using: self.uiWebViewPrintFormatter())
print(uiPDFData)
DispatchQueue.main.async{
let fileURL = NSURL(fileURLWithPath: (uiPDFData))
// Create the Array which includes the files you want to share
var filesToShare = [Any]()
// Add the path of the file to the Array
filesToShare.append(fileURL)
// Make the activityViewContoller which shows the share-view
let activityViewController = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
// Show the share-view
if UIDevice.current.userInterfaceIdiom == .pad {
if let popup = activityViewController.popoverPresentationController {
popup.sourceView = self.view
popup.sourceRect = CGRect(x: self.view.frame.size.width / 2, y: self.view.frame.size.height / 4, width: 0, height: 0)
}
}
self.present(activityViewController, animated: true, completion: nil)
}

UIGraphicsBeginPDFContextToData does not show image after pdf creation

I am working on the HtmltoPDF creation. It is working fine when some image URL but not working with my server image URL.
Working URL downloaded from the google
Issue in the server image URL
I have put here my code for the pdf generation. Please find it
func exportHTMLContentToPDF(HTMLContent: String) -> String {
let printPageRenderer = IPPrintPageRenderer()
let printFormatter = UIMarkupTextPrintFormatter(markupText: HTMLContent)
printPageRenderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)
let pdfData = drawPDFUsingPrintPageRenderer(printPageRenderer: printPageRenderer)
let str = "\(Global.kretriveUserData().firstName!.firstCharacter!)\(Global.kretriveUserData().Name!.firstCharacter!)".uppercased()
pdfFilename = "\(getDocDir())/\(str + invoiceNumber!).pdf"
pdfData?.write(toFile: pdfFilename, atomically: true)
print(pdfFilename)
return pdfFilename
}
func drawPDFUsingPrintPageRenderer(printPageRenderer: UIPrintPageRenderer) -> NSData! {
let data = NSMutableData()
UIGraphicsBeginPDFContextToData(data, CGRect.zero, nil)
for i in 0..<printPageRenderer.numberOfPages {
UIGraphicsBeginPDFPage()
printPageRenderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())
}
UIGraphicsEndPDFContext()
return data
}
func getDocDir() -> String {
return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
}
You can find a full demo here.
Thanks,
To generate a pdf from a webView you need to prepare your HTML code, create the WebView and inject the HTML code inside the webView and in webView didFinishLoading print the HTML content inside the pdf using the same width and height of the webView.
func webViewDidFinishLoad(_ webView: UIWebView) {
let render = UIPrintPageRenderer()
render.addPrintFormatter(webView.viewPrintFormatter(), startingAtPageAt: 0);
let page = CGRect(x: 0, y: 10, width: webView.frame.size.width, height: webView.frame.size.height) // take the size of the webView
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();
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
print(documentsPath)
pdfData.write(toFile: "\(documentsPath)/pdfName.pdf", atomically: true)
self.pdfPath = "\(documentsPath)/pdfName.pdf"
self.pdfTitle = "pdfName"
self.performSegue(withIdentifier: "showPDFSegue", sender: nil)
webView.removeFromSuperview()
self.loadingScreenViewController.view.removeFromSuperview()
}
Happy coding:)

Swift Save UITextView Text to .Pdf, .Doc and .Txt file formate and Display

My Scenario, I am trying to save UITextView Text with Three format .pdf, .doc and .txt. Here, formate option user can choose based on alert option. Once Its saved need to show in Preview controller for file sharing. How to achieve this?
func createPDF(text:String, filename:String) {
// 1. Create Print Formatter with input text.
let formatter = UIMarkupTextPrintFormatter(markupText: text)
// 2. Add formatter with pageRender
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 rect = CGRect.zero
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, rect, nil)
for i in 1...render.numberOfPages {
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
render.drawPage(at: i - 1, in: bounds)
}
UIGraphicsEndPDFContext();
// 5. Save PDF file
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
pdfData.write(toFile: "\(documentsPath)/\(filename).pdf", atomically: true)
print("saved success:\(documentsPath)\(filename)")
listFiles()
}
Try the following code :)
let txtData = Data(textView.txt.utf8)
do {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let filePath = (documentsPath as NSString).appendingPathComponent("\(filename).pdf")
let url = URL(fileURLWithPath: filePath)
// pdfData created by your code above
// txtData for ".txt"
pdfData.write(to: url)
let activityVC = UIActivityViewController(activityItems: [url], applicationActivities: nil)
// Use your desired viewController here, or just use the rootViewController
UIApplication.shared.keyWindow?.rootViewController?.presentViewController(activityVC, animated: true, completion: nil)
} catch (let error) {
print("\(error)")
}
If i understand correct you need show documents
You can do this with QLPreviewController
More info in -
https://developer.apple.com/documentation/quicklook
https://developer.apple.com/documentation/quicklook/qlpreviewcontroller#//apple_ref/occ/cl/QLPreviewController
https://medium.com/#garg.vivek/quick-display-documents-with-qlpreviewcontroller-eaca97928c7a
QLPreviewController have sharing control

Open the pdf file automatically after saving it

My app creates a pdf file when I hit enter button. I do this by the code below. At the moment I want to open the saved file automatically after saving.
The code for saving:
#IBAction func EnterButtonAction(_ sender: AnyObject) {
let html = "PDF FILE TITLE"
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: 1000) // 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();
// Save PDF file
let path = "\(NSTemporaryDirectory())MyAppFile.pdf"
pdfData.write(toFile: path, atomically: true)
print("open \(path)") // command to open the generated file
}
You can open your PDF file using UIDocumentInteractionController and find the below code:
func showFileWithPath(path: String){
let isFileFound:Bool? = NSFileManager.defaultManager().fileExistsAtPath(path)
if isFileFound == true{
let viewer = UIDocumentInteractionController(URL: NSURL(fileURLWithPath: path))
viewer.delegate = self
viewer.presentPreviewAnimated(true)
}
}
pdfData.write(toFile: path, atomically: true); is synchronous call, so you can write code to open file directly after this line, but first check if file is written successfully .
var success = pdfData.write(toFile: path, atomically: true);
if success {
//Write code to open file in Webview or UIDocumentInteractionController
}

Create and store PDF document programmatically using Swift for iOS

I have an app that can view a PDF that is already stored within the project. I want to be able to create a new PDF document and store it in the app directory to later view in the already existing viewer. The PDF would be created from an array var todoList: [String] = [] that is displayed on a UITableView. I know to create a PDF, I have to create a file name, path, and directory. I don't know how to do this. I saw online reference to URL and URL request, but I'm not sure if this is the correct avenue for what I want to do. Can someone please give me some advice and guidance? Everything I can find is for Objective-C.
I used this code to create and save the file (using HTML)
func createPDF() {
let html = "<b>Hello <i>World!</i></b> <p>Generate PDF file from HTML in Swift</p>"
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 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, .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 documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
pdfData.write(toFile: "\(documentsPath)/file.pdf", atomically: true)
}
Then I loaded it into UIWebView from the documents directory with this code:
func loadPDF(filename: String) {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let url = URL(fileURLWithPath: documentsPath, isDirectory: true).appendingPathComponent(filename).appendingPathExtension("pdf")
let urlRequest = URLRequest(url: url)
webView.loadRequest(urlRequest)
}
For Swift 3:
createPdf() {
// 1. Create Print Formatter with input text.
let formatter = UIMarkupTextPrintFormatter(markupText: textView.text)
// 2. Add formatter with pageRender
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 rect = CGRect.zero
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, rect, nil)
for i in 1...render.numberOfPages {
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
render.drawPage(at: i - 1, in: bounds)
}
UIGraphicsEndPDFContext();
// 5. Save PDF file
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
pdfData.write(toFile: "\(documentsPath)/new.pdf", atomically: true)
print("saved success")
}

Resources