Rename the download pdf file using swift iOS - ios

I am successfully downloading a PDF from api end point. Once pdf is downloaded, the title of pdf is : PDF document.pdf .
How to change the title of PDF?
I tried to update metadata of PDF using PDFDocumentAttribute (see below), but it is not working.
var metadata = pdfDocument.documentAttributes!
metadata[PDFDocumentAttribute.subjectAttribute] = "subject attribute"
metadata[PDFDocumentAttribute. titleAttribute] = "title attribute"
pdfDocument.documentAttributes = metadata
Note: I am not using FileManager
How I am fetching PDF:-
let task = session.dataTask(with: urlRequest) { (data, _, error) in
DispatchQueue.main.async {
guard let unwrappedData = data, error == nil else {
completion(.failure(error ?? Constants.dummyError))
return
}
guard let pdfDocument = PDFDocument(data: unwrappedData) else {
completion(.failure(error ?? Constants.dummyError))
return
}
completion(.success(pdfDocument))
}
}

try this:
pdfDocument.documentAttributes?["Title"] = "my title attribute"
or
pdfDocument.documentAttributes?[PDFDocumentAttribute.titleAttribute] = "my title attribute"
Similarly for PDFDocumentAttribute.subjectAttribute.
The above will set the Title of your document, and when you save it, the file name will be whatever file name you give it.
EDIT-1: saving the pdfDocument to a file with a chosen file name.
DispatchQueue.main.async {
guard let unwrappedData = data, error == nil else {
completion(.failure(error ?? Constants.dummyError))
return
}
guard let pdfDocument = PDFDocument(data: unwrappedData) else {
completion(.failure(error ?? Constants.dummyError))
return
}
// set the Title
pdfDocument.documentAttributes?[PDFDocumentAttribute.titleAttribute] = "my title attribute"
do {
// save the document to the given file name ("mydoc.pdf")
let docURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("mydoc.pdf") // <-- here file name
pdfDocument.write(to: docURL)
print("\n docUrl: \(docURL.absoluteString)\n")
}
catch {
print("Error \(error)")
}
completion(.success(pdfDocument))
}

Related

Getting "The file couldn’t be opened because there is no such file" error from FileManager even though it's actually opened

I'm retrieving a plist file, updating it, and writing it to disk.
1) Retrieval
func pListURL() -> URL? {
guard let result = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("somePlist.plist") else { return nil }
return result
}
2) Update
var data: [String: Int] = [:]
if let url = pListURL() {
do {
let dataContent = try Data(contentsOf: url)
if let dict = try PropertyListSerialization.propertyList(from: dataContent, format: nil) as? [String: Int] {
data = dict
}
} catch {
print(error)
}
}
// update code
3) Write
if let path = pListURL() {
do {
let plistData = try PropertyListSerialization.data(fromPropertyList: data, format: .xml, options: 0)
try plistData.write(to: path)
} catch {
print(error)
}
}
The odd thing is I get an error that says:
The file “somePlist.plist” couldn’t be opened because there is no such file.
even though when I check the plist, it's actually properly created and updated as it should be. As far as I know, the create parameter of FileManager.default.url(for:in:appropriateFor:create: ) ensures that it "creates the directory if it does not already exist", which means somePlist.plist is created if plist doesn't exist already.
As far as I know, the create parameter of FileManager.default.url(for:in:appropriateFor:create: ) ensures that it "creates the directory if it does not already exist", which means somePlist.plist is created if plist doesn't exist already.
No, it means the directory is created but the file is not created.
In the update part ignore the couldn’t be opened error and write the (new) data to disk or check if the file exists with fileExists(atPath.
And you can declare the return value in pListURL as non-optional. It's guaranteed that the folder Documents exists
func pListURL() -> URL {
return try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("somePlist.plist")
}
Update:
These are reliable versions of update and write
func update(dictionary: [String:Int]) {
let url = pListURL()
guard FileManager.default.fileExists(atPath: url.path) else { write(dictionary: dictionary); return }
do {
let dataContent = try Data(contentsOf: url)
if var dict = try PropertyListSerialization.propertyList(from: dataContent, format: nil) as? [String: Int] {
for (key, value) in dictionary {
dict.updateValue(value, forKey: key)
}
write(dictionary: dict)
} else {
write(dictionary: dictionary)
}
} catch {
print(error)
}
}
func write(dictionary: [String:Int]) {
let url = pListURL()
do {
let plistData = try PropertyListSerialization.data(fromPropertyList: dictionary, format: .xml, options: 0)
try plistData.write(to: url)
} catch {
print(error)
}
}

issue while preview pdf from remoteURL

i am implementing pdf preview in my Swift app so i have decided to use third party library for Preview PDF i am using below library
Please Check Library Here
so first i am download url and store to document directory and than i am displaying it but pdf not previewed below is my code
func downloadFileFromURL(url: String) {
if let audioUrl = URL(string: url) {
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
print(destinationUrl)
if FileManager.default.fileExists(atPath: destinationUrl.path) {
print("The file already exists at path")
print(destinationUrl)
let document = try! PDFDocument(filePath: destinationUrl.lastPathComponent, password: "")
self.collectionView.document = document
} else {
URLSession.shared.downloadTask(with: audioUrl, completionHandler: { (location, response, error) -> Void in
guard let location = location, error == nil else { return }
do {
try FileManager.default.moveItem(at: location, to: destinationUrl)
print(destinationUrl)
let document = try! PDFDocument(filePath: destinationUrl.lastPathComponent, password: "")
self.collectionView.document = document
print("File moved to documents folder")
} catch let error as NSError {
print(error.localizedDescription)
}
}).resume()
}
}
}
and inside viewDidLoad() i am implementing below code
downloadFileFromURL(url: "http://housedocs.house.gov/edlabor/AAHCA-BillText-071409.pdf")
but still pdf is not previewed can some tell me its the right way to preview pdf with UXMPdf
or suggest me best pdfviewer for Swift from which i can load pdf from URL
You have to specify the full path rather than the last path component.
And remove the ! inside a do - catch block.
let document = try PDFDocument(filePath: destinationUrl.path, password: "")
As the password parameter is unused I recommend to use the built-in initializer
let document = try PDFDocument(url: destinationUrl)

Contact image not getting when fetch all contact list from iPhone by CNContact

I know this question already asked but not getting solution.
From this code I will get all the information from the contact but image not found when open vcf files on mac os, also not getting when share this file. I use this stackoverflow link here but It's not help full.
var contacts = [CNContact]()
let keys = [CNContactVCardSerialization.descriptorForRequiredKeys()
] as [Any]
let request = CNContactFetchRequest(keysToFetch: keys as! [CNKeyDescriptor])
do {
try self.contactStore.enumerateContacts(with: request) {
(contact, stop) in
// Array containing all unified contacts from everywhere
contacts.append(contact)
}
} catch {
print("unable to fetch contacts")
}
do {
let data = try CNContactVCardSerialization.data(with: contacts)
if let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let fileURL = directoryURL.appendingPathComponent("contacts").appendingPathExtension("vcf")
print(fileURL)
do {
try data.write(to: fileURL, options: .atomic)
} catch {
print("error \(error)")
}
}
} catch {
print("error \(error)")
}
Probably,
let data = try CNContactVCardSerialization.data(with: contacts)
Only adds the contact info without image tag, and hence you need to add image tag manually into your VCF file. you can find the solution here.
https://stackoverflow.com/a/44308365/5576675
Yes,
let data = try CNContactVCardSerialization.data(with: contacts)
give only contacts info not image data so you need to do like this, you can get correct VCF files.
var finalData = Data()
for contact in contacts {
do {
var data = try CNContactVCardSerialization.data(with: [contact])
var vcString = String(data: data, encoding: String.Encoding.utf8)
let base64Image = contact.imageData?.base64EncodedString()
let vcardImageString = "PHOTO;TYPE=JPEG;ENCODING=BASE64:" + (base64Image ?? "") + ("\n")
vcString = vcString?.replacingOccurrences(of: "END:VCARD", with: vcardImageString + ("END:VCARD"))
data = (vcString?.data(using: .utf8))!
finalData += data
} catch {
print("error \(error)")
}
}
if let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let fileURL = directoryURL.appendingPathComponent("contacts").appendingPathExtension("vcf")
do {
try finalData.write(to: fileURL, options: .atomic)
} catch {
print("error \(error)")
}
}

How to upload CSV file in google drive in swift 3

I am using google drive SDK for uploading CSV file. I used code given in google but error is coming
func create(){
let fileData = FileManager.default.contents(atPath: "FL_insurance_sample.csv")
let folderId: String = self.fileId!
let metadata = GTLRDrive_File.init()
metadata.name = "FL_insurance_sample"
metadata.mimeType = "application/vnd.google-apps.spreadsheet"
metadata.parents = [folderId]
let uploadParameters = GTLRUploadParameters(data: fileData! , mimeType: "text/csv")
uploadParameters.shouldUploadWithSingleRequest = true
let query = GTLRDriveQuery_FilesCreate.query(withObject: metadata, uploadParameters: uploadParameters)
query.fields = "id"
self.service.executeQuery(query, completionHandler: {(ticket:GTLRServiceTicket, object:Any?, error:Error?) in
if error == nil {
// print("File ID \(files.identifier)")
}
else {
print("An error occurred: \(error)")
}
})
}
It showing nil error on uploadParameters at fileData. Can anyone help me out.
Variable fileData is nil because you've passed the wrong file path. To get correct file path use:
guard let filePath = Bundle.main.path(forResource: "FL_insurance_sample", ofType: "csv") else {
print("No such file in bundle")
// handle situation
return
}
guard let fileData = FileManager.default.contents(atPath: filePath) else {
print("Can't read file")
// handle situation
return
}
// upload fileData

unable to overwrite the text file

I'm trying to overwrite the existing file everytime the application is started. I have tried two things both are not working.
1) I'm trying to create the file getting downloaded from online server with the same name but the data in the file is not getting updated, my code is..
let documentsUrl:URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
let destinationFileUrl = documentsUrl.appendingPathComponent("Splash.text")
let fileURL = URL(string:(defaults.object(forKey: "MainAddress") as! String).appending(filedownloadLink)
print("proper url = \(String(describing: fileURL))")
let sessionConfig = URLSessionConfiguration.default
let session1 = URLSession(configuration: sessionConfig)
print("splash file url \(destinationFileUrl)")
let request = URLRequest(url:fileURL!)
let task1 = session1.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
}
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
let fileManager = FileManager.default
// Check if file exists
} catch (let writeError) {
print("Error creating a file \(destinationFileUrl) : \(writeError)")
}
} else {
print("Error took place while downloading a file. Error description: %#", error?.localizedDescription);
}
}
task1.resume()
2) then i tried checking for the file before creating it, and if it exists then i'm deleting it. but once the file is deleted it is not getting opened with an error saying file "splash.text" doesnot exist. below is the code
do{
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = URL(fileURLWithPath: path)
let filePath = url.appendingPathComponent("Splash.text").path
let fileManager1 = FileManager.default
if fileManager1.fileExists(atPath: filePath) {
print("FILE AVAILABLE")
try fileManager1.removeItem(atPath: filePath)
} else {
print("FILE NOT AVAILABLE")
}
}
catch let error as NSError {
print("An error took place: \(error)")
}
and after this code I'm calling the code of method 1. I'm not sure why it is not getting created again for 2nd method, or why it is not overwritting it in 1st.

Resources