Search code examples
iosswiftpdfuiimagensurlsession

Swift UIImage convert as PDF


In my App have to sale UIImage from iPad Gallery and convert into PDF and save on Server side.

I can select the image and send it to server side , but Backend says that pdf is empty(null data)

I also see the warning/error in my console : [discovery] errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo={NSLocalizedDescription=query cancelled}

Where am I going wrong? Thank you in advance!

Code I tried

//Opens gallery to select Image
func clickImage() {

    let image = UIImagePickerController()
    image.delegate = self
    image.sourceType = UIImagePickerControllerSourceType.photoLibrary
    image.allowsEditing = false
    self.present(image, animated: true, completion: nil)

}

//image picker function
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
         scannedPhoto.image = image
    } else{
        print("Something went wrong")
    }

    self.dismiss(animated: true, completion: nil)

    uploadAttachment()

}

//Convert UIImage to PDF
func createPDF(image: UIImage) -> NSData? {

    let pdfData = NSMutableData()
    let pdfConsumer = CGDataConsumer(data: pdfData as CFMutableData)!

    var mediaBox = CGRect.init(x: 0, y: 0, width: image.size.width, height: image.size.height)

    let pdfContext = CGContext(consumer: pdfConsumer, mediaBox: &mediaBox, nil)!

    pdfContext.beginPage(mediaBox: &mediaBox)
    pdfContext.draw(image.cgImage!, in: mediaBox)
    pdfContext.endPage()
    return pdfData
}

// custom body of HTTP request to upload pdf file
func createBody(_ parameters: [String: String]?, filePathKey: String?, imageDataKey: Data, boundary: String) -> Data {

    let body = NSMutableData()

    if parameters != nil {
        for (key, value) in parameters! {
            body.appendString("--\(boundary)\r\n")
            body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
            body.appendString("\(value)\r\n")
        }
    }

    let filename = "ava.pdf"

    let mimetype = "pdf"

    body.appendString("--\(boundary)\r\n")
    body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
    body.appendString("Content-Type: \(mimetype)\r\n\r\n")
    body.append(imageDataKey)
    body.appendString("\r\n")

    body.appendString("--\(boundary)--\r\n")

    return body as Data

}
//Function to send converted pdf server side
func uploadAttachment() {


    let pdfdata = createPDF(image: scannedPhoto.image!)


    // url path to php file
    let url = URL(string: "\(Config.path)/uploadAva.php")!

    // declare request to this file
    var request = URLRequest(url: url)

    // declare method of passign inf to this file
    request.httpMethod = "POST"

    // param to be sent in body of request
    let param = ["AppId":Config.AppID , "uuid":Config.uuid , "Id" : userId]

    // body
    let boundary = "Boundary-\(UUID().uuidString)"
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    // ... body
    request.httpBody = createBodyWithParams(param, filePathKey: "file", imageDataKey: pdfdata! as Data, boundary: boundary) 

    // launc session
    // warning I receive here
    URLSession.shared.dataTask(with: request) { data, response, error in
        //do anything here
    }
}

Solution

  • create pdf file data as:

    func createPDFDataFromImage(image: UIImage) -> NSMutableData {
        let pdfData = NSMutableData()
        let imgView = UIImageView.init(image: image)
        let imageRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
        UIGraphicsBeginPDFContextToData(pdfData, imageRect, nil)
        UIGraphicsBeginPDFPage()
        let context = UIGraphicsGetCurrentContext()
        imgView.layer.render(in: context!)
        UIGraphicsEndPDFContext()
    
        //try saving in doc dir to confirm:
        let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
        let path = dir?.appendingPathComponent("file.pdf")
    
        do {
                try pdfData.write(to: path!, options: NSData.WritingOptions.atomic)
        } catch {
            print("error catched")
        }
    
        return pdfData
    }
    

    enter image description here