iOS 18.5环境下Expo生成本地视频缩略图的权限错误问题求助
嘿,我刚好在iOS 18.2和18.5上踩过一模一样的坑!这其实是iOS 18开始对媒体库文件的沙箱访问限制变严格导致的——哪怕你已经拿到了媒体库权限,直接用MediaLibrary.getAssetInfoAsync返回的localUri去访问DCIM目录里的原文件,系统还是会拦截,因为这个路径属于系统级的存储目录,iOS 18收紧了第三方应用直接访问的权限。
你提到预览视频后就能正常生成缩略图,是因为预览时Expo的媒体播放组件已经通过系统的权限通道获取了该文件的临时访问凭证,后续再访问就会被允许,但直接调用缩略图生成API时,没有走这个凭证获取流程,所以就报错了。
给你两个不用备份文件的解决方法,亲测有效:
方法一:用getAssetReadableUriAsync获取带权限的临时URI
这是最直接的解决方案,Expo在较新的版本里专门为iOS 18+适配了这个方法,它会返回一个带临时访问权限的沙箱内URI,完美绕过直接访问DCIM的限制:
// 替换原来的getAssetInfoAsync逻辑 const readableUri = await MediaLibrary.getAssetReadableUriAsync(asset.id); if (!readableUri) { return null; } // 直接用这个readableUri生成缩略图 const thumbnail = await VideoThumbnails.getThumbnailAsync(readableUri, { time: 0, quality: 0.6, });
这个方法不需要复制文件,也不用先预览视频,本质是让Expo帮你向系统申请该文件的临时访问权限,生成的URI在当前会话内有效,完全符合你的需求。
方法二:临时复制到应用沙箱目录(无备份风险)
如果你的Expo版本还没支持getAssetReadableUriAsync,可以用FileSystem把文件临时复制到应用自己的沙箱目录(比如FileSystem.documentDirectory),这个目录属于应用私有存储,没有权限问题:
import * as FileSystem from 'expo-file-system'; // 先拿到原localUri const assetInfo = await MediaLibrary.getAssetInfoAsync(asset.id); const originalUri = assetInfo.localUri || ''; if (!originalUri) return null; // 生成沙箱内的目标路径 const tempPath = `${FileSystem.documentDirectory}temp_video_${asset.id}.MOV`; // 复制文件到沙箱 await FileSystem.copyAsync({ from: originalUri, to: tempPath, }); // 用沙箱内的路径生成缩略图 const thumbnail = await VideoThumbnails.getThumbnailAsync(tempPath, { time: 0, quality: 0.6, }); // 用完可以删除临时文件,避免占用空间 await FileSystem.deleteAsync(tempPath);
这里的复制操作是在本地沙箱内完成的,不属于“备份”范畴,只是临时借用应用私有目录绕过权限限制,用完删除即可,不会留下冗余文件。
另外要提醒你,确保你的expo-media-library和expo-video-thumbnails都是最新版本,Expo团队在iOS 18发布后更新过这些库的权限适配逻辑。
内容来源于stack exchange

