You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让iOS应用访问从Files应用分享的文件URL?

iOS应用访问Files应用共享URL的解决方案

问题根源

从Files应用(包括iCloud Drive、「我的iPhone」路径)共享的URL属于iOS安全范围资源,这类路径不在你的应用沙盒内,直接调用FileManager.default.fileExists(atPath:)会因权限不足返回不存在;而WhatsApp等应用是将文件直接复制到你应用沙盒的Documents/Inbox目录,所以原有逻辑能正常处理。

解决步骤

核心是通过iOS提供的安全范围资源访问API获取临时权限,再进行文件操作:

  1. 获取临时访问权限
    在application:openURL:options:方法中,先通过url.startAccessingSecurityScopedResource()获取目标文件/文件夹的临时访问权限,该方法返回true表示权限获取成功。

  2. 安全判断文件状态
    权限获取成功后,再用FileManager.default.fileExists(atPath:isDirectory:)判断目标是文件还是文件夹,避免无权限时的误判。

  3. 处理文件/文件夹

    • 如果是单个文件:将其复制到你应用沙盒的Documents/Inbox目录(保持原有逻辑的兼容性)
    • 如果是文件夹:遍历文件夹内的文件,逐个复制到目标目录
  4. 释放权限
    操作完成后必须调用url.stopAccessingSecurityScopedResource()释放临时权限,避免资源泄漏。

代码示例

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    guard url.isFileURL else { return false }
    
    var isDirectory: ObjCBool = false
    // 申请临时访问权限
    guard url.startAccessingSecurityScopedResource(),
          FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory) else {
        return false
    }
    
    // 确保操作完成后释放权限
    defer {
        url.stopAccessingSecurityScopedResource()
    }
    
    // 获取应用沙盒的Inbox目录路径
    let inboxURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        .appendingPathComponent("Inbox")
    // 确保Inbox目录存在
    try? FileManager.default.createDirectory(at: inboxURL, withIntermediateDirectories: true)
    
    if isDirectory.boolValue {
        // 处理共享的文件夹:遍历所有文件并复制
        if let fileURLs = try? FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil) {
            for fileURL in fileURLs {
                let destURL = inboxURL.appendingPathComponent(fileURL.lastPathComponent)
                try? FileManager.default.copyItem(at: fileURL, to: destURL)
            }
        }
    } else {
        // 处理单个文件:直接复制到Inbox
        let destURL = inboxURL.appendingPathComponent(url.lastPathComponent)
        try? FileManager.default.copyItem(at: url, to: destURL)
    }
    
    return true
}

注意事项

  • 不要省略stopAccessingSecurityScopedResource(),否则会导致应用后续无法正常获取其他安全范围资源的权限
  • 如果需要直接读取文件内容(而非复制),也必须在获取临时权限后进行操作
  • 无需额外配置Info.plist权限,只要通过上述API处理即可访问Files共享的资源

内容的提问来源于stack exchange,提问作者Deddiekoel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 00:27:06