从Firebase Cloud Functions将图像上传至云存储

3
我正在努力从云函数上传一张图片。我使用onRequest方法从网页向云函数发送了一个base64字符串和文件名。我查看了不同的教程,但似乎无法解决我的问题。 这是我的代码。我觉得我在服务帐户json方面做错了什么。尽管我生成了json文件并使用了它,但仍然无法正常工作。 当我没有使用服务帐户json时,我会收到“调用者没有权限”错误。 当我使用serviceAccount.json时,我会收到“path”参数必须为字符串类型的错误,出现在“file.createWriteStream()”中。 无论如何,以下是我的代码,请问有谁能帮我解决这个问题? 我使用的projectId显示在下面的图片中。
const functions = require("firebase-functions");
const admin = require("firebase-admin");

const projectId = functions.config().apikeys.projectid; // In the picture below

const stream = require("stream");

const cors = require("cors")({ origin: true });

const { Storage } = require("@google-cloud/storage");
//  Enable Storage
const storage = new Storage({
  projectId: projectId, // I did use serviceAccount json here but that wasn't working
});




// With serviceAccount.json code
// const storage = new Storage({
//      projectId: projectId,
//      keyFilename: serviceAccount,
//    });
// This is giving the error of: The "path" argument must be of type string. Received an instance of Object
    
exports.storeUserProfileImage = functions.https.onRequest((req, res) => {
  cors(req, res, async () => {
    try {
      const bucket = storage.bucket(`gs://${projectId}.appspot.com`);

      let pictureURL;
      const image = req.body.image;
      const userId = req.body.userId;
      const fileName = req.body.fileName;

      const mimeType = image.match(
        /data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/
      )[1];
      //trim off the part of the payload that is not part of the base64 string
      const base64EncodedImageString = image.replace(
        /^data:image\/\w+;base64,/,
        ""
      );
      const imageBuffer = Buffer.from(base64EncodedImageString, "base64");
      const bufferStream = new stream.PassThrough();
      bufferStream.end(imageBuffer);
      // Define file and fileName
      const file = bucket.file("images/" + fileName);

      bufferStream
        .pipe(
          file.createWriteStream({
            metadata: {
              contentType: mimeType,
            },
            public: true,
            validation: "md5",
          })
        )
        .on("error", function (err) {
          console.log("error from image upload", err.message);
        })
        .on("finish", function () {
          // The file upload is complete.
          console.log("Image uploaded");
          file
            .getSignedUrl({
              action: "read",
              expires: "03-09-2491",
            })
            .then((signedUrls) => {
              // signedUrls[0] contains the file's public URL
              console.log("Signed urls", signedUrls[0]);
              pictureURL = signedUrls[0];
            });
        });
      console.log("image url", pictureURL);
      res.status(200).send(pictureURL);
    } catch (e) {
      console.log(e);
      return { success: false, error: e };
    }
  });
});

enter image description here


1
请在使用服务账户的代码中包含该服务账户。 - Victor Eronmosele
没有翻译意义的文本。请提供需要翻译的内容。 - Sulman Azhar
2个回答

2
const storage = new Storage({
  projectId: projectId
  keyFilename: "" // <-- Path to a .json, .pem, or .p12 key file
});

keyFilename 接受存储您的服务帐号和凭据本身的路径。

folder
  |-index.js
  |-credentials
    |-serviceAccountKey.json

如果你的目录结构看起来像这样,路径应该是这样的:
const storage = new Storage({
  projectId: projectId
  keyFilename: "./credentials/serviceAccountKey.json"
});

请注意,如果您正在使用云函数,则SDK将使用应用程序默认凭据,因此您不必传递这些参数。只需按照下面所示进行初始化即可:
const storage = new Storage()

我已经这样做了,但我认为服务器端没有这个文件。基本上在云中,所以我遇到了这个错误。虽然我在本地设置中有这个文件。 图像上传错误 ENOENT:没有这样的文件或目录,打开'/swmcontactportal-firebase-adminsdk-hl76c-3ad043c522.json'。 - Sulman Azhar
这可能是因为这段代码const bucket = storage.bucket(`gs://${projectId}.appspot.com`);。我正在使用默认文件夹存储桶中存储选项卡提供的链接,您可以在此图片中查看https://i.imgur.com/5aOHI9R.png。 - Sulman Azhar
@SulmanAzhar 尝试使用 storage.bucket("您的存储桶名称") 而不是完整的 URL。在这种情况下,它将是 projectId。 - Dharmaraj
非常感谢,我已经解决了。显然,在Google Cloud平台上存在权限问题,同时也提供了与此类似的存储桶链接:const bucket = storage.bucket(`gs://${projectId}.appspot.com`) - Sulman Azhar
您应该使用想要访问的项目的服务帐号。 - Dharmaraj
显示剩余2条评论

1
首先,我没有提供任何服务帐户,因为我正在使用 Firebase 云函数,正如 @Dharmaraj 在他的答案中所说。 其次,这是 Google Cloud 平台中的权限问题,可以通过以下步骤解决: 前往您的项目的 Cloud 控制台 (https://console.cloud.google.com/) > IAM 和管理 > IAM,在“应用引擎默认服务帐户”中找到铅笔,单击添加角色,在过滤字段中输入“服务帐户令牌创建器”,单击保存即可。 从这里找到了这个解决方案 https://github.com/firebase/functions-samples/issues/782

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接