首页 > 解决方案 > 部署后本地运行HTTP功能时无法访问存储文件

问题描述

所以我的firestore集合用户中有一些错误的记录:图像字段(错误的路径:users/uid/name.jpg,预期输出:

https://firebasestorage.googleapis.com/v0/b/project-id.appspot.com/o/users%2F4yWeML3ktpVt6oWowtEhg8oJx1I3%2Fcropped828392415291985722.jpg?alt=media&token=6daeeab9-6b34-4a27-a4d5-0789a7d773c3

) - 存储中的图像保存为:

users > user_id > cropped{fileName}.jpg

所以我写了一个云函数来从桶'用户'中获取所有文件

import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
import { Storage } from "@google-cloud/storage";
admin.initializeApp({
  credential: admin.credential.cert({
    projectId: "myProjectId",
    clientEmail:
      "firebase-adminsdk-myAdmin@project-id.iam.gserviceaccount.com",
    privateKey:
      "-----BEGIN PRIVATE KEY-----\nmyprivatekey=\n-----END PRIVATE KEY-----\n"
  }),
  storageBucket: "myProject.appspot.com"
});

const db = admin.firestore();
const storage = new Storage({
  projectId: "myProjectId",
  credentials: {
    client_email: "firebase-adminsdk-myAdmin@project-id.iam.gserviceaccount.com",
    private_key:  "-----BEGIN PRIVATE KEY-----\nMyPrivateKey=\n-----END PRIVATE KEY-----\n"
  }
});

export const updateUserImage = functions.https.onRequest((request, response) => {
    const wrongData: any = [];
    db.collection("users")
      .where("image", ">=", "/users")
      .orderBy("image", "asc")
      .get()
      .then(res => {
        res.forEach(ele => {
          if (ele.data().hasOwnProperty("image")) {
            console.log(ele.data().image.includes("/firebasestorage"));
            if (!ele.data().image.includes("/firebasestorage")) {
              wrongData.push(ele);
            }
          }
        });
        console.log('Wrong docs: ' + wrongData.length);
        for (const doc of wrongData) {
          const getFileName = doc.data().image.split("/")[3];
          const subFolder = doc.data().image.split("/")[2];
          console.log(getFileName);
          storage.bucket('users').file(`${subFolder}/${getFileName}`).get()
          .then((fileData: any) => {
            console.log(fileData);
          }).catch(err => console.log(err))
        }
      })
      .catch(err => console.log(err));
  }
);

我部署了此功能,然后使用 firebase 模拟器在本地进行测试,所有包都在 package.json 中更新为最新:

"dependencies": {
    "@google-cloud/firestore": "^2.2.6",
    "@google-cloud/storage": "^3.1.0",
    "@google/maps": "^0.5.5",
    "@types/google__maps": "^0.5.5",
    "express": "^4.17.1",
    "firebase": "^6.3.5",
    "firebase-admin": "^8.3.0",
    "firebase-functions": "^3.2.0"
  },

但是,当我通过命令进行调试时:firebase serve --only functions 即使管理 SDK 可以获取数据,但是当从存储中获取文件时,它会抛出错误:

{ Error: firebase-adminsdk-xtk2b@project-id.iam.gserviceaccount.com does not have storage.objects.get access to users/4yWeML3ktpVt6oWowtEhg8oJx1I3/cropped828392415291985722.jpg. }

我上网并设置了谷歌云存储的权限 - 此帐户的谷歌云平台控制台,包括角色:

  1. Firebase admin SDK 管理代理(生成 json 时由 Google 默认)

  2. 存储管理员

  3. 所有者

  4. 存储对象管理员

然后等待 5 分钟,但当我尝试在本地调用该函数时仍然出现同样的错误。配置中缺少什么吗?我对云功能和云存储有点陌生

标签: typescriptgoogle-cloud-firestoregoogle-cloud-functionsgoogle-cloud-storagefirebase-tools

解决方案


您的代码正在尝试访问名为“users”的存储桶中的文件:

storage.bucket('users')

但我 100% 确定您的存储桶名称不是“用户”。存储桶名称与出现在存储桶中的“文件夹”的名称不同。您的存储桶的名称更有可能与您的项目 ID 匹配,或者它是您在创建它时编造的全球唯一名称(在所有 Google Cloud 中的所有项目中的所有存储桶中)。


推荐阅读