NSFileProvider importDocument从MSOffice保存新文档时返回空文件URL
解决Word.app通过FileProvider扩展导入空文件的问题
我之前在做FileProvider扩展时也碰到过类似的情况,给你几个实用的排查和解决方向:
1. 确保安全作用域文件访问的正确处理
你的代码里用到了startAccessing,但很可能没处理完整的权限生命周期,这会导致无法正确读取文件内容。必须保证获取权限后一定释放,并且先验证权限获取成功再继续操作:
override func importDocument(at fileURL: URL, toParentItemIdentifier parentItemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) { // 先验证是否能获取文件访问权限 guard fileURL.startAccessingSecurityScopedResource() else { completionHandler(nil, NSError(domain: NSFileProviderErrorDomain, code: NSFileProviderError.notAuthenticated.rawValue, userInfo: [NSLocalizedDescriptionKey: "无法访问源文件权限"])) return } // 用defer确保无论代码走哪个分支,都会释放权限 defer { fileURL.stopAccessingSecurityScopedResource() } let internalUrl = NSFileProviderManager.default.documentStorageURL.appendingPathComponent(fileURL.lastPathComponent, isDirectory: false) do { // 先校验源文件是否有效 guard FileManager.default.fileExists(atPath: fileURL.path) else { throw NSError(domain: NSFileProviderErrorDomain, code: NSFileProviderError.noSuchItem.rawValue, userInfo: [NSLocalizedDescriptionKey: "源文件不存在"]) } let fileSize = try FileManager.default.attributesOfItem(atPath: fileURL.path)[.size] as! UInt64 guard fileSize > 0 else { throw NSError(domain: NSFileProviderErrorDomain, code: NSFileProviderError.invalidItem.rawValue, userInfo: [NSLocalizedDescriptionKey: "源文件为空"]) } // 执行文件复制 try FileManager.default.copyItem(at: fileURL, to: internalUrl) // 创建自定义的FileProviderItem并返回 let item = YourCustomFileProviderItem(url: internalUrl, parentIdentifier: parentItemIdentifier) completionHandler(item, nil) } catch { completionHandler(nil, error) } }
2. 排查第三方App的文件写入时机
有时候像Word这类第三方App,可能在文件还没完全写入磁盘时就触发了importDocument调用,导致传递的fileURL对应的文件是空的。你可以:
- 在代码中增加文件大小校验(如上例),如果为空则返回错误,让Word重新触发导入
- 尝试在接收文件后添加短暂延迟(比如0.5秒)再读取,不过这种方式不太优雅,仅作为临时调试手段
3. 检查FileProvider扩展的文档类型配置
确保你的扩展Info.plist中正确配置了支持Word文档的UTI类型,否则Word可能不会正确传递完整文件:
在NSExtensionAttributes下添加:
<key>NSFileProviderSupportedDocumentTypes</key> <array> <dict> <key>UTTypeConformsTo</key> <array> <string>public.wordprocessing</string> </array> <key>UTTypeIdentifier</key> <string>com.microsoft.word.doc</string> </dict> <dict> <key>UTTypeConformsTo</key> <array> <string>public.wordprocessing</string> </array> <key>UTTypeIdentifier</key> <string>org.openxmlformats.wordprocessingml.document</string> </dict> </array>
4. 调试时的关键日志
可以在importDocument开头添加日志,明确问题根源:
print("接收的源文件URL: \(fileURL)") print("文件是否存在: \(FileManager.default.fileExists(atPath: fileURL.path))") if let attrs = try? FileManager.default.attributesOfItem(atPath: fileURL.path) { print("文件大小: \(attrs[.size] as? UInt64 ?? 0) bytes") }
通过这些日志你能快速判断:是文件本身为空,还是权限问题导致无法读取,亦或是文件根本不存在。
内容的提问来源于stack exchange,提问作者abjurato
相关产品推荐
相关产品推荐

