Firestore新建含Cloud Storage图片URL文档时如何生成缩略图?
前置依赖安装
执行以下命令安装图片处理库:
npm install sharp @types/sharp
完整实现代码
import * as functions from "firebase-functions"; import * as admin from "firebase-admin"; import * as sharp from "sharp"; admin.initializeApp(); const firestore = admin.firestore(); const storage = admin.storage(); export const generateThumbnailOnCreate = functions // 配置云函数最小内存256MB,避免图片处理时内存不足 .runWith({ memory: "256MB" }) .firestore.document("missions/{missionId}") .onCreate(async (snap, context) => { const doc = snap.data(); const missionImgUrl = doc.mission_img_url; // 无图片URL直接跳过处理 if (!missionImgUrl) return; try { // 步骤1:从下载URL解析出存储桶和文件路径 const urlObj = new URL(missionImgUrl); const pathParts = urlObj.pathname.split("/"); const bucketName = pathParts[3]; // 解码文件路径 const fullFilePath = decodeURIComponent(pathParts[4]); const bucket = storage.bucket(bucketName); const originalFile = bucket.file(fullFilePath); // 步骤2:下载原图到内存 const [originalFileBuffer] = await originalFile.download(); // 步骤3:生成100px宽度的缩略图,高度自适应 const thumbnailBuffer = await sharp(originalFileBuffer) .resize({ width: 100, withoutEnlargement: true }) // 小图不强制放大 .jpeg({ quality: 80 }) // 可根据需求调整格式和质量 .toBuffer(); // 步骤4:生成缩略图存储路径,和原图同目录 const pathSegments = fullFilePath.split("/"); const fileName = pathSegments.pop() || ""; const [name, ext] = fileName.split("."); const thumbFileName = `${name}_thumb.${ext}`; const thumbFilePath = [...pathSegments, thumbFileName].join("/"); const thumbFile = bucket.file(thumbFilePath); // 步骤5:上传缩略图到Storage await thumbFile.save(thumbnailBuffer, { contentType: "image/jpeg", public: false, // 和原图权限保持一致即可 }); // 步骤6:获取缩略图永久下载URL const [thumbnailImgUrl] = await thumbFile.getSignedUrl({ action: "read", expires: "03-01-2500", // 设置极长过期时间等价永久有效,和客户端getDownloadUrl效果一致 }); // 步骤7:更新回Firestore文档 await snap.ref.update({ thumbnail_img_url: thumbnailImgUrl }); console.log("缩略图生成并更新成功"); } catch (err) { console.error("缩略图处理失败:", err); } });
注意事项
- 云函数默认服务账号需要拥有Storage的读写权限,通常默认初始化的admin权限已经满足
- 如果需要生成PNG/GIF等格式的缩略图,修改sharp的输出配置即可
- 若原图可能不存在,可增加
originalFile.exists()判断逻辑避免报错
内容的提问来源于stack exchange,提问作者Johntopia
相关产品推荐
相关产品推荐

