HTTP onCall函数读取Cloud Storage文件报错,如何解决并提取邮箱?
解决Firebase Cloud Functions读取Cloud Storage文件的错误
错误原因
你遇到的TypeError [ERR_INVALID_ARG_TYPE]是因为**fs.readFile的第一个参数必须是文件路径、Buffer或URL**,但你传入了file.createReadStream()返回的流对象(PassThroughShim是Storage流的内部实现类),这不符合readFile的参数要求。
解决方案
推荐使用Cloud Storage SDK提供的download()方法直接读取文件内容,比手动处理流更简洁可靠。同时结合async/await优化代码结构,避免回调嵌套:
修改后的完整代码
const functions = require('firebase-functions') const admin = require('firebase-admin') const { getStorage } = require('firebase-admin/storage') admin.initializeApp() const bucket = getStorage().bucket() exports.readCSVFile = functions.https.onCall(async (data, context) => { // 验证用户身份(可选,但onCall默认已验证,可添加额外检查) if (!context.auth) { throw new functions.https.HttpsError('unauthenticated', '用户未登录') } const filePath = `users/${context.auth.uid}/customers` const file = bucket.file(filePath) // 检查文件是否存在 const [exists] = await file.exists() if (!exists) { throw new functions.https.HttpsError('not-found', 'customers文件不存在') } // 读取文件内容 const [fileBuffer] = await file.download() const contents = fileBuffer.toString('utf8') // 提取所有邮箱地址(正则匹配) const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g const emails = contents.match(emailRegex) || [] return { emails } })
关键修改点说明
- 替换
fs.readFile为file.download():该方法直接返回文件内容的Buffer,转成字符串即可使用,无需手动处理流。 - 全程使用
async/await:替代then/catch链式调用,代码更易读,错误处理更直观。 - 添加邮箱提取逻辑:通过正则表达式匹配文本中的邮箱地址,无匹配时返回空数组。
- 完善错误处理:确保所有错误都抛出
HttpsError,客户端能正确接收错误类型和信息。
备选方案:手动处理流(仅作参考)
如果一定要用流读取,可将流的读取过程封装为Promise:
// 封装流读取为Promise function streamToString(stream) { return new Promise((resolve, reject) => { const chunks = [] stream.on('data', (chunk) => chunks.push(chunk)) stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8'))) stream.on('error', reject) }) } // 在函数中使用 const stream = file.createReadStream() const contents = await streamToString(stream)
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

