Home > Software engineering >  How to save base64 string into PDF in swift?
How to save base64 string into PDF in swift?

Time:07-15

I'm receiving a pdf as base64 string, then I want to save that into Firebase storage bucket. So to my knowledge the process is:

  1. put binary data into base64 string
  2. make base64 string into data

but I'm getting nil when trying to convert the string into Data (note that I'm actually getting data from the response, but when converting to data in swift from a base64 string I get nil...)

is there a special syntax to convert base64 to Data so I can save the pdf into firebase?

Swift function

  func getAssetReportPDF(){
        self.hasLoaded = false;
        let json: [String: Any] = [
            "assetReportToken": UserDefaults.standard.value(forKey: "asset_report_token") as! String
        ]
        
        Functions.functions().httpsCallable("getAssetReportPdf").call(json) { (result, error) in
            if let error = error {
                debugPrint(error.localizedDescription)
                return
            }
            
            let result = result?.data as! String
            print(result)
            //convert the string base64 into Data
            let dataPDF = Data(base64Encoded: result)
            //let dataPDF = Data(base64Encoded: result!.data)
            //let dataPDF = NSData(base64Encoded: result?.data, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) as Data?
            
            //write it in firebase bucket(PDF)
            let storage = Storage.storage()
            //let user = UserService.shared.user
            
            let uploadMetaData = StorageMetadata()
            uploadMetaData.contentType = "application/pdf"
            
            //create unique file name using phone number
            let documentID = UserDefaults.standard.string(forKey: "phone")
            
            //SAVE pdf TO STORAGE
            ///reference to storage root, bucket is userDocument id, then files are photo uploaded with a unique id
            let storageRef = storage.reference().child(documentID!).child(documentID!)
            let uploadTask = storageRef.putData(dataPDF!, metadata: uploadMetaData){
                (_, err) in
                if let err = err {
                    print("an error has occurred - \(err.localizedDescription)")
                } else {
                    print("pdf uploaded successfully")
                    
                    ///SAVE pdf URL AS REFERENCE IN USER COLLECTION
                    let db = Firestore.firestore()
                    
                    let ref = db.collection("users").document(documentID!)
                    
                    //download URL of the pic just posted
                    storageRef.downloadURL { url, error in
                        
                        ref.setData(["asset_report": url!.absoluteString ], merge: true) { err in
                            if let err = err {
                                print("Error writing pdf url: \(err)")
                            } else {
                                print("url successfully saved!")
                            }
                            
                        }
                        
                    }
                }
            }
            
            //save the report id in firebase and the pdf as well

        }
    }

cloud function in node.js

exports.getAssetReportPdf = functions.https.onCall(async (data, context) => {
  const assetReportToken = data.assetReportToken;

  const configuration = new Configuration({
    basePath: PlaidEnvironments[functions.config().app.env],
    baseOptions: {
      headers: {
        "PLAID-CLIENT-ID": functions.config().plaid.client_id,
        "PLAID-SECRET": functions.config().plaid.secret,
      },
    },
  });

  const plaidClient = new PlaidApi(configuration);

  return plaidClient
    .assetReportPdfGet({
      asset_report_token: assetReportToken
    })
    .then((response) => {
      //prettyPrintResponse(response);
      //const pdf = response.buffer.toString('base64');
      const pdf = response.data.toString('base64');
      return pdf; //I need to save it in FIREBASE stack
    })
    .catch((err) => {
      console.log(err);
      throw new functions.https.HttpsError(
        "internal",
        "Unable to download pdf "   err
      );
    });
});

CodePudding user response:

Can you try like this, first you create PDF file then verify that the received base64 string got converted into pdf or not. Then, you can upload the file to Firebase, once it is uploaded you can delete the same file from the Documents directory.

/// This will creates a PDF file
func createPDF(with base64Info: String) {
    let base64Data = Data(base64Encoded: base64Info, options: .ignoreUnknownCharacters)
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let filePath = "\(documentsPath)/{your_pdf_filename}.pdf"
    if FileManager.default.fileExists(atPath: filePath) {
        let url = URL(fileURLWithPath: filePath)
        do{
            try base64Data?.write(to: url, options: .atomic)
        }catch let failedError {
            print("Failed to write the pdf data due to \(failedError.localizedDescription)")
        }
    }else{
        print("Failed to write the pdf data")
    }
}

/// Verify your created PDF file
func verifyPDF() {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let filePath = "\(documentsPath)/{your_pdf_filename}.pdf"
    let url = URL(fileURLWithPath: filePath)
    let webView = WKWebView()
    webView.load(URLRequest(url: url))
}

CodePudding user response:

I was missing to specify responseType: 'arraybuffer' in my cloud function

return plaidClient
    .assetReportPdfGet({
      asset_report_token: assetReportToken
    },
    {
    responseType: 'arraybuffer',
    })
    .then((response) => {
      const pdf = response.data.toString('base64');
      return pdf; 
    })
    .catch((err) => {
      console.log(err);
      throw new functions.https.HttpsError(
        "internal",
        "Unable to download pdf "   err
      );
    });
});
  • Related