在 iOS 13 中从外部存储读取文件

Posted

技术标签:

【中文标题】在 iOS 13 中从外部存储读取文件【英文标题】:Reading files from external storage in iOS 13 【发布时间】:2020-03-03 00:54:16 【问题描述】:

我有一个 ios 应用程序正在尝试从外部存储设备读取文件而不将它们导入应用程序的沙箱。

我已按照此处列出的 Apple 文档执行此操作 --

Providing Access to Directories

我能够检索所选目录(位于通过 Lightning 端口连接的外部存储设备上)并枚举目录中的文件。

但是,当我尝试按照推荐的模式对这些文件执行某些操作时,我遇到了失败,并且基本上得到了文件的权限错误。

        let shouldStopAccessing = pickedFolderURL.startAccessingSecurityScopedResource()
        defer 
          if shouldStopAccessing 
            pickedFolderURL.stopAccessingSecurityScopedResource()
          
       
       var coordinatedError:NSError?
       NSFileCoordinator().coordinate(readingItemAt: pickedFolderURL, error: &coordinatedError)  (folderURL) in
        let keys : [URLResourceKey] = [.isDirectoryKey]
        let fileList = FileManager.default.enumerator(at: pickedFolderURL, includingPropertiesForKeys: keys)!
        for case let file as URL in fileList 
            if !file.hasDirectoryPath 
                do 
                    // Start accessing a security-scoped resource.
                    guard file.startAccessingSecurityScopedResource() else 
                        // Handle the failure here.
                        //THIS ALWAYS FAILS!!
                        return
                    

                    // Make sure you release the security-scoped resource when you are done.
                    defer  file.stopAccessingSecurityScopedResource() 

我应该补充一点,如果文件通过模拟器在 iCloud Drive 上,这可以正常工作。它在外部设备和真实设备上的 iCloud Drive 上都失败。

Here 是一个完整的工作项目,它演示了失败。

    在模拟器上运行可以正常访问 iCloud Drive 文件。但在设备上运行失败。 在设备上运行以访问 USB 驱动器失败。

【问题讨论】:

我确实看到了您的代码与 Apple 提供的示例代码之间的一个主要区别;你说的是guard file.startAccessingSecurityScopedResource() else return ,但苹果说的是else continue 。这会有所作为吗?如果 first 文件失败,你就放弃了,但也许那个文件有些有趣。 @matt -- 感谢您的评论。我已经尝试了许多不同的文件来确定。 我很好奇,您到底想对所选目录做什么?从您的代码看来,您希望对所有内容进行可变写入,对吗? @DanielGalasko——不。我只想阅读那里的文件。该目录包含一堆我想阅读和播放的 mp3 文件。 您是否尝试先将文件复制到临时目录然后从中读取? 【参考方案1】:

因此,这似乎是上面发布的链接的文档问题。当用户选择一个文件夹时,所有文件和文件夹都被递归授予访问权限并自动设置安全范围。 guard file.startAccessingSecurityScopedResource() 行总是返回 false。

完成这项工作的诀窍不是尝试对单个文件进行安全范围,而是确保此代码 sn-p 在您访问文件之前不会运行。

   defer 
      if shouldStopAccessing 
        pickedFolderURL.stopAccessingSecurityScopedResource()
      
   

只要您在pickedFolderURL 处于安全范围内时继续访问文件,您就会成功。

希望这对某人有所帮助。

【讨论】:

以上是关于在 iOS 13 中从外部存储读取文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在带有 cordova 的 iOS 设备中从 iCloud 读取文件?

如何在 C# 中从外部站点的 url 读取 PDF 文件 [关闭]

在bash中从用户输入中读取文件并存储在变量中。

在 Golang 中从 AWS S3 读取文件

如何在 App Engine 中从 Google Storage 读取 zip 文件?

如何在 Android 10、Target API 29 中从设备的共享存储(根目录)读取现有文件? [复制]