云函数中向Firebase Storage写入文件的更优方法咨询
问题:Cloud Functions中更规范地将API获取的文件写入Firebase Storage
Firestore和Firebase Storage的核心区别很明确:Firestore用于存储结构化数据(对象、数组、字符串等),而Storage专门存储文件,在Cloud Functions里处理这两者的逻辑差异很大。
我用Node调用外部API获取音频文件后想写入Storage,但觉得Node操作起来有点麻烦,目前找到的方法感觉不太规范:
index.ts
import { getStorage, ref, uploadBytes, uploadString, connectStorageEmulator } from "firebase/storage"; import got from 'got'; const storage = getStorage(); const storageRef = ref(storage, 'audio/winter_us_2.mp3'); const file = await got('https://audio.oxforddictionaries.com/en/mp3/winter__us_2.mp3'); await uploadBytes(storageRef, file['rawBody'], { contentType: 'audio/mpeg' });
这里通过file['rawBody']调用响应体,总觉得不太妥当,有没有更优的规范写法?
更规范的实现方式
其实不需要绕路,uploadBytes本身支持传入Buffer类型的参数,而got返回的rawBody本质就是Buffer,直接用file.rawBody(而非方括号语法)就已经是规范用法了。不过还有两种更清晰的实现方式:
方式一:明确获取Buffer并上传
调用got时指定responseType: 'buffer',可以更直白地拿到Buffer类型的响应体,代码可读性更高:
import { getStorage, ref, uploadBytes } from "firebase/storage"; import got from 'got'; const storage = getStorage(); const storageRef = ref(storage, 'audio/winter_us_2.mp3'); // 显式指定获取Buffer格式的响应 const fileResponse = await got('https://audio.oxforddictionaries.com/en/mp3/winter__us_2.mp3', { responseType: 'buffer' }); await uploadBytes(storageRef, fileResponse.body, { contentType: 'audio/mpeg' // 务必指定正确的文件MIME类型 });
方式二:流式上传(适合大文件场景)
如果处理的是大文件,流式上传可以避免把整个文件加载到内存,更节省Cloud Functions的资源:
import { getStorage, ref, uploadBytesResumable } from "firebase/storage"; import got from 'got'; const storage = getStorage(); const storageRef = ref(storage, 'audio/winter_us_2.mp3'); // 创建可恢复的流式上传任务 const uploadTask = uploadBytesResumable(storageRef, got.stream('https://audio.oxforddictionaries.com/en/mp3/winter__us_2.mp3'), { contentType: 'audio/mpeg' }); // 可选:监听上传状态变化 uploadTask.on('state_changed', (snapshot) => { const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; console.log(`上传进度:${progress.toFixed(2)}%`); }, (error) => { console.error('上传失败:', error); }, () => { console.log('文件上传完成'); } ); // 等待上传任务结束 await uploadTask;
注意事项
- 必须指定
contentType:如果省略这个元数据,Storage会默认把文件标记为application/octet-stream,后续访问或下载时可能无法正确识别文件类型(比如音频无法直接播放)。 - 语法规范:
file['rawBody']和file.rawBody功能完全等价,但后者的点语法是JavaScript/TypeScript的标准写法,代码更易读维护。
内容的提问来源于stack exchange,提问作者Thomas David Kehoe
相关产品推荐
相关产品推荐

