【问题标题】:Picking a Folder from iCloud with Document Picker使用文档选择器从 iCloud 中选择一个文件夹
【发布时间】:2019-05-01 11:23:55
【问题描述】:

我正在尝试使用文档选择器从 iCloud 导入一个文件夹,以使用 Alamofire 将其上传到服务器。我可以从 iCloud 导入单个文件,例如 .txt .pdf 文件,但我无法选择其中包含一些文件的文件夹。尝试选择文件夹后出现以下错误:

无法加载数据:Error Domain=NSCocoaErrorDomain Code=257 "The 文件 “xxxx”无法打开,因为您没有权限 查看它。” ... {Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"}}

这是我的代码:

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 来自文档选择器功能,如下所示:

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

我试图找到解决方案将近 2 天,但我似乎找不到解决方案。如何从 iCloud 中选择一个文件夹,为什么我会收到此权限被拒绝错误?任何回应都将受到高度赞赏。

【问题讨论】:

  • 如何在 didPickDocumentAt 中获取文件夹?根据文档,这是不可能的,从逻辑上讲,我也看不到它,当您点击文件夹时,它必须打开内容,以便可以以任何方式选择它......?
  • 我想我可以在允许文档选择器多选后选择一个文件夹。

标签: ios swift file-management uidocumentpickervc


【解决方案1】:

请记住,当涉及到 iCloud 时,您处于沙盒中,因此您需要使用 FileManager 来获取适当的文件。

例如

  1. 确保项目中勾选了“iCloud Documents”
  2. 指定容器,例如您在 developer.apple.com 上指定的容器。 Xcode 会自动为您执行此操作,并且会显示为 iCloud.com.yourapp.identifier.whatever.abb
  3. 确保为您的应用启用了 iCloud,同样,如果您在其中正确设置了开发人员 ID,Xcode 将为您执行此操作(Xcode -> Preferences -> Accounts (tab)... 添加它那里..

现在有了一些代码魔法,你就可以开始了。虽然这有点复杂,但它是正确的方法(恕我直言有点太正确了):

https://theswiftdev.com/2018/05/17/how-to-use-icloud-drive-documents/

但是你需要依赖FileManager(旧的NSFileManager)

【讨论】:

    【解决方案2】:

    您收到此错误是因为您正在获取文件所在文件夹的路径,并且就像 @ivan-ičin 在 cmets 中所说的那样,您无法根据文档从 iCloud 中选择整个文件夹。

    因此,如果您尝试将特定文件夹的所有文件上传到您的服务器,我建议您获取该文件夹的 URL,然后使用下面的代码,您可以获得该文件夹中存在的所有文件的列表。

    您可以通过以下方式获取您尝试选择的文档文件夹中存在的所有文件的列表。

    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)")
    } 
    

    一旦您获得 URL,您可以将它们附加到一个数组中,然后使用 Alamofire 将它们一一上传到您的服务器。

    【讨论】:

    • 哦,我还以为允许多选后就可以选择文件夹了。非常感谢您的帮助和清晰的解释。它有效!
    • 由于我的声誉,我无法支持您的回答。
    • @NilayDagdemir 您最欢迎。如果有效,请接受此作为正确答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多