SMB挂载点自定义QuickLook插件可行性咨询
核心结论
完全可以实现只针对SMB挂载路径下的文件使用自定义QL生成器,不需要修改文件的UTI(也做不到),而是通过路径过滤让自定义生成器仅处理SMB路径的文件,其他路径自动 fallback 到系统默认生成器。
关于UTI的误区
UTI是基于文件本身的类型(扩展名、内部签名)定义的,和文件存储的位置(SMB/本地/DropBox)无关,所以没办法给SMB里的文件单独定义新UTI。但你可以让自定义生成器关联常见文件的UTI,再通过代码判断路径来决定是否处理。
为什么DropBox的QL生成器不影响全局
DropBox的QL生成器虽然在info.plist里关联了大量UTI,但它的内部代码做了路径校验——只有DropBox同步文件夹内的文件才会用它的生成器,其他路径的文件会直接返回不处理,系统就会自动用默认生成器。这也是qlmanage -m显示默认生成器的原因。
实现步骤
创建QL扩展项目
用Xcode新建QuickLook Extension模板的项目,命名比如SMBThumbnailQLGenerator。配置支持的文件类型
在扩展的info.plist里,找到QLSupportedContentTypes数组,添加需要覆盖的常见UTI:- 图片:
public.image - PDF:
public.pdf - MP4:
public.mpeg-4
(可以添加更多你需要的类型,比如public.audio等)
- 图片:
添加路径过滤逻辑
在生成器的主代码(比如SMBThumbnailQLGenerator.swift)里,实现generateThumbnail和generatePreview方法时,先判断文件是否在SMB挂载路径:func generateThumbnail(for url: URL, with context: QLThumbnailGenerationContext, completionHandler: @escaping (QLThumbnailReply?, Error?) -> Void) { // 判断是否为SMB挂载路径 guard let volumeURL = try? url.resourceValues(forKeys: [.volumeURLKey]).volumeURL, volumeURL.scheme == "smb" else { // 不是SMB路径,交给默认生成器 completionHandler(nil, nil) return } // 调用你的缩略图服务器API获取缩略图 fetchThumbnailFromServer(fileURL: url) { imageData in guard let data = imageData, let image = NSImage(data: data) else { // 获取失败, fallback 到默认 completionHandler(nil, nil) return } // 返回生成的缩略图 let reply = QLThumbnailReply(contextSize: image.size) { context in image.draw(in: CGRect(origin: .zero, size: image.size)) return true } completionHandler(reply, nil) } }(预览方法
generatePreview的逻辑类似,只是返回QLPreviewReply)配置网络权限
如果你的缩略图服务器是HTTP协议,需要在扩展的info.plist里添加NSAppTransportSecurity字典,开启NSAllowsArbitraryLoads;如果是HTTPS则不需要额外配置。
测试与验证
- 安装扩展后,用
qlmanage -p /Volumes/你的SMB共享/测试文件.jpg来测试,看是否调用了你的自定义生成器。 - 用
qlmanage -m generators查看生成器的优先级,确保你的生成器被系统识别。
内容的提问来源于stack exchange,提问作者viral_mutant

