Firebase Storage触发云函数报bucket属性未定义TypeError
错误根因
- 核心报错来自Cloud Functions Storage触发器API版本不兼容:参考的5年前旧版代码适配的是老版firebase-functions,
firebase-functions@3.x及以上版本中,onFinalize回调的第一个参数直接就是存储对象实例,不存在event.data嵌套,所以取object.bucket时实际访问的是undefined.bucket,直接抛出类型错误。 - 其次
@google-cloud/vision@2.x版本的类型引用方式变更,旧的Vision.v1.types.Feature.Type.XXX路径已经失效,直接传对应类型字符串即可,否则会触发类型不存在的报错。 - 最后Swift端存在文件名不匹配的逻辑问题:上传时固定用了
images/file.png作为存储路径,但是监听Firestore时却生成了新的UUID作为文档ID,两边路径完全不对应,就算云函数正常写入也监听不到数据。
修复方案
1. 替换云函数index.js代码
const Vision = require('@google-cloud/vision'); const vision = new Vision.ImageAnnotatorClient(); const functions = require('firebase-functions'); const admin = require("firebase-admin"); admin.initializeApp(); // 新版admin初始化无需传入functions.config().firebase exports.callVision = functions.storage.object().onFinalize(async (object) => { // 过滤非图片、临时文件,避免无效触发 if (!object.name || !object.contentType.startsWith('image/')) { return null; } const fileBucket = object.bucket; const filePath = object.name; const gcsPath = `gs://${fileBucket}/${filePath}`; // 新版Vision API直接传类型字符串即可,无需引用内部嵌套类型 const req = { image: {source: {imageUri: gcsPath}}, features: [ { type: 'WEB_DETECTION' }, { type: 'SAFE_SEARCH_DETECTION' } ], }; console.log('开始处理图片:', gcsPath); try { const [response] = await vision.annotateImage(req); const visionResp = { web: response.webDetection, safe: response.safeSearchAnnotation }; const db = admin.firestore(); // 去掉路径前缀images/,和存储文件名保持一致作为文档ID const docId = filePath.replace(/^images\//, ''); await db.collection('images').doc(docId).set(visionResp); console.log('数据写入Firestore成功,文档ID:', docId); return null; } catch (err) { console.error('Vision API处理失败:', err); throw err; // 抛出错误触发函数重试,不要静默吞错 } });
2. 修复Swift端逻辑问题
原代码存在两个问题:一是上传时固定文件名file.png会导致每次上传覆盖旧文件;二是监听时生成的UUID和实际上传文件名不匹配,永远拿不到结果。修复后的核心代码如下:
func retrieveAPIData(imageName: String) { print("开始监听分析结果,图片名:\(imageName)") // 用实际上传的文件名作为文档ID监听 self.firestore.collection("images").document(imageName) .addSnapshotListener { documentSnapshot, error in if let error = error { print("监听出错:", error) return } guard let data = documentSnapshot?.data() else { print("文档暂未生成,等待中...") return } print("拿到Vision分析结果:", data) } } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { picker.dismiss(animated: true, completion: nil) guard let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage else { return } guard let imageData = image.pngData() else { return } // 生成唯一文件名,避免覆盖旧文件 let imageName = "\(UUID().uuidString).png" let imageRef = storage.child("images/\(imageName)") imageRef.putData(imageData, metadata: nil, completion: {_, error in if let error = error { print("图片上传失败:", error) return } print("图片上传成功,开始监听结果") // 传入实际文件名启动监听 self.retrieveAPIData(imageName: imageName) }) }
部署验证步骤
- 在云函数目录执行
npm install确认所有依赖安装正确 - 执行
firebase deploy --only functions部署修复后的云函数 - 重新运行iOS端测试,上传图片后可在云函数日志看到处理成功打印,Firestore中会生成对应文档,iOS端可正常拿到分析结果。
内容的提问来源于stack exchange,提问作者ddd
相关产品推荐
相关产品推荐

