Search code examples
iosswiftfile-managementuidocumentpickervc

Picking a Folder from iCloud with Document Picker


I'm trying to import a folder from iCloud with Document Picker to upload it to a server, using Alamofire. I can import a single file like .txt .pdf files from iCloud, but I can't pick a folder which has some files in it. I'm getting the following error after trying to select a folder:

Unable to load data: Error Domain=NSCocoaErrorDomain Code=257 "The file “xxxx” couldn’t be opened because you don’t have permission to view it." ... {Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"}}

And here is my code:

someFunctionToGetPickedFilePath = { (filePath) in
        let urlString = filePath.path
        let fileWithPath: URL = URL.init(fileURLWithPath: urlString)

        do {
            let fileData = try Data(contentsOf: fileWithPath)
            // upload the fileData to server with Alamofire upload request
        } catch {
            print("Unable to load data: \(error)")
        }
    }

"filePath" URL in here comes from document picker function like this:

func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
    // some code 
}

I am trying to find a solution for almost 2 days but I cannot seem to find a solution. How can I pick a folder from iCloud and why am I getting this permission denied error? Any response will be highly appreciated.


Solution

  • You are getting this error because you are getting the path of the folder in which your files exist and like @ivan-ičin has said in the comments you cannot pick an entire folder from iCloud according to the documentation.

    So if you are trying to upload all the files of a specific folder to your server i would suggest you get the URL of the folder and then using the below code you can get a list all the files present in that folder.

    Here is how you can get a list of all the files present in the documents folder that you are trying to pick.

    let fileManager = FileManager.default
    let documentsURL = "YOUR FOLDER URL"
    //If all files are in your app document directory then use this line
    //fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
    
    do {
        let fileURLs = try fileManager.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil)
        // Append files to an array here and then iterate the array later and upload files to server one by one.
    } catch {
        print("Error while enumerating files \(documentsURL.path): \(error.localizedDescription)")
    } 
    

    Once you get the URLs you can append them to an array and upload them one by one to your server using Alamofire.