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

macOS NSFileProvider无法获取文件项,下载后Finder打开提示文件为空

NSFileProvider fetchContents方法返回有效文件后Finder提示为空的修复方案

根因说明

该问题是NSFileProvider扩展开发中的常见实现错误,核心原因有两点:

  1. 临时文件权限不足:NSFileProviderManager生成的临时目录默认仅对扩展进程本身开放读取权限,Finder作为外部进程访问时没有权限读取内容,会误判为0字节空文件
  2. 元数据没有同步更新:系统会缓存FileProvider Item的contentVersion、documentSize等元数据,如果你返回了新的文件内容但没有同步更新对应item的元数据字段,系统会沿用旧的缓存信息,判断文件为空

修复步骤

  • 复制文件到临时路径后,显式为文件添加全局读权限,保证外部进程可访问
  • 回调completionHandler前更新item的contentVersion、documentSize属性,和实际下载的文件信息匹配,刷新系统缓存
  • 不要提前删除临时目录下的目标文件,保证completionHandler执行完成前文件可用

修正后参考代码

let task = downloadItem(named: filename) { url, error in
    guard let sourceURL = url, error == nil else {
        completionHandler(nil, nil, Error.fileDownloadFailed)
        return
    }
    let dataURL = NSFileProviderManager.default.temporaryDirectoryURL.appendingPathComponent(filename)
    
    do {
        // 先删除可能存在的旧临时文件
        try? FileManager.default.removeItem(at: dataURL)
        try FileManager.default.copyItem(at: sourceURL, to: dataURL)
        // 显式设置全局读权限
        try FileManager.default.setAttributes([.posixPermissions: 0o644], ofItemAtPath: dataURL.path)
        // 获取实际文件大小,更新item元数据
        let fileAttrs = try FileManager.default.attributesOfItem(atPath: dataURL.path)
        let fileSize = fileAttrs[.size] as? Int ?? 0
        item.documentSize = NSNumber(value: fileSize)
        // 生成新的contentVersion,可用文件哈希+时间戳保证唯一性
        item.contentVersion = "\(fileSize)_\(Date().timeIntervalSince1970)" as NSString
        completionHandler(dataURL, item, nil)
    } catch {
        completionHandler(nil, nil, Error.fileDownloadFailed)
    }
}
task.progress.cancellationHandler = { 
    completionHandler(nil, nil, NSError(domain: NSCocoaErrorDomain, code: NSUserCancelledError)) 
}
return task.progress

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:36:04