使用Firebase Admin发送推送通知时图片时有时无的问题求助
针对你遇到的推送通知图片间歇性显示问题,结合技术栈与代码,从以下方向排查修复:
1. 异步流程错误导致请求异常
你的sendNotifMultiCast函数中,async.forEach的callback()未等待sendMulticast请求完成就直接调用,会引发两个问题:
- 并发发起大量Firebase API请求,触发平台限流,导致部分推送处理不完整
deliveredUsers和failedUsers统计完全失真,无法反映真实推送结果
修复代码:
将callback()移到sendMulticast的then/catch回调内,改用async.eachLimit控制并发数(比如限制同时处理5个chunk),避免请求过载:
async.eachLimit( tokensArr, 5, // 可根据Firebase API限额调整并发数 (tokensChunk, callback) => { const payload = { notification: { title, body, image }, data: { navigateto }, tokens: tokensChunk, }; firebaseAdmin .messaging() .sendMulticast(payload) .then((resp) => { const { successCount, failedCount, individualResults } = resp; deliveredUsers += successCount; failedUsers += failedCount; // 记录失败的token及原因,方便定位问题 individualResults.forEach((result, index) => { if (!result.success) { console.log(`Token ${tokensChunk[index]} 推送失败: ${result.error.message}`); } }); callback(); }) .catch((err) => { console.log("notif err===>>>", err); callback(err); }); }, (err) => { console.log( `notifLog===>>> sentUsers=${sentUsers}, deliveredUsers=${deliveredUsers}, failedUsers=${failedUsers}` ); } );
2. 跨平台通知图片字段适配
仅在notification.image设置图片,可能导致Android/iOS平台兼容性问题,引发间歇性失效。需添加平台专属配置:
const payload = { notification: { title, body, image }, android: { notification: { image: image, // 明确指定Android端通知图片 priority: "high" // 高优先级确保通知及时送达并加载图片 } }, apns: { payload: { aps: { "mutable-content": 1 // 允许iOS端通过通知扩展加载图片 } }, fcm_options: { image: image // iOS端专属图片字段 } }, data: { navigateto }, tokens: tokensChunk, };
3. Azure Blob的CORS配置检查
Firebase需要从服务器端拉取通知图片,如果Azure Blob的CORS策略未允许Firebase访问,会导致图片加载失败。
配置步骤:
- 登录Azure门户,找到目标存储账户
- 进入「资源共享(CORS)」设置
- 添加规则:
- 允许的来源:
*(或限制为https://fcm.googleapis.com) - 允许的方法:
GET - 允许的标头:
* - 公开的标头:
* - 最大年龄:
86400
- 允许的来源:
4. 图片URL稳定性验证
确保Azure Blob图片URL为公开可访问状态,避免使用带过期时间的SAS URL(若必须使用SAS,需确保有效期覆盖推送全时段)。可直接在浏览器中访问URL,验证是否能稳定加载。
另外,建议为图片添加缓存控制头(如Cache-Control: public, max-age=31536000),让CDN与Firebase更好地缓存图片,降低加载失败概率。
5. 无效Token清理
部分用户Token可能已过期或失效,虽聚合查询过滤了空值,但仍可能存在无效Token。通过individualResults记录失败原因,将标记为UNREGISTERED或INVALID_ARGUMENT的Token从数据库中移除,减少无效请求占用资源。
内容的提问来源于stack exchange,提问作者Guru Sahoo

