如何在Expo iOS通知中发送本地文件附件?
Expo环境下UNNotificationAttachment图片附件失效问题解决
针对你遇到的「Invalid attachment file URL」报错,以下是Expo环境下的针对性解决方案:
核心问题根源
Expo的通知附件API仅识别沙箱内特定目录下的file://协议URI,直接使用本地资源的asset:// URI或第三方库的临时目录路径都会触发权限或格式校验失败。
分步解决方法
1. 改用Expo官方FileSystem指定目录复制文件
放弃react-native-fs的TempDirectoryPath,使用Expo提供的FileSystem.cacheDirectory或FileSystem.documentDirectory,这两个目录是通知API有权限访问的合法路径:
import * as FileSystem from 'expo-file-system'; // 本地资源URI(asset://格式) const sourceUri = require('../assets/your-image.png').uri; // 目标路径:转换为file://格式的缓存目录路径 const targetUri = `${FileSystem.cacheDirectory}notification-attachment.png`; // 执行文件复制 await FileSystem.copyAsync({ from: sourceUri, to: targetUri, });
2. 验证文件有效性与权限
复制完成后,必须确认文件存在且可读,避免因复制失败导致的无效URI:
const fileInfo = await FileSystem.getInfoAsync(targetUri); if (!fileInfo.exists || !fileInfo.isFile) { throw new Error('附件文件复制失败或不存在'); }
3. 正确构造附件对象
确保附件的url是完整的file:// URI,identifier唯一,typeHint匹配文件实际类型:
import * as Notifications from 'expo-notifications'; const attachments: Notifications.NotificationContentAttachmentIos[] = [ { identifier: 'unique-image-attachment', // 唯一标识 url: targetUri, // 必须是file://开头的路径 options: { typeHint: 'image/png', // 与文件扩展名匹配,如image/jpeg thumbnailHidden: false, }, }, ];
4. 完整通知调度流程
确保已获取通知权限,再将附件传入调度参数:
// 先请求通知权限 const { status } = await Notifications.requestPermissionsAsync(); if (status !== 'granted') { alert('需要授予通知权限才能使用附件功能'); return; } // 调度通知 await Notifications.scheduleNotificationAsync({ content: { title: '带图片的通知', body: '这是包含图片附件的测试通知', attachments, }, trigger: { seconds: 2 }, });
避坑提醒
- 禁止直接使用
asset://格式的URI作为附件URL,必须转换为file://路径 - 不要使用非Expo官方的临时目录,避免权限访问问题
- 文件名避免特殊字符,使用简单的字母数字组合+正确扩展名
内容的提问来源于stack exchange,提问作者Archimedes Trajano
相关产品推荐
相关产品推荐

