使用 Node.js 将文件上传到 Firebase 存储

IT技术 javascript node.js firebase gcloud firebase-storage
2021-01-20 07:49:33

我试图了解如何使用 Node.js 在 Firebase 存储中上传文件。我的第一次尝试是使用 Firebase 库:

"use strict";

var firebase = require('firebase');

var config = {
    apiKey: "AIz...kBY",
    authDomain: "em....firebaseapp.com",
    databaseURL: "https://em....firebaseio.com",
    storageBucket: "em....appspot.com",
    messagingSenderId: "95...6"
};

firebase.initializeApp(config);

// Error: firebase.storage is undefined, so not a function
var storageRef = firebase.storage().ref();

var uploadTask = storageRef.child('images/octofez.png').put(file);

// Register three observers:
// 1. 'state_changed' observer, called any time the state changes
// 2. Error observer, called on failure
// 3. Completion observer, called on successful completion
uploadTask.on('state_changed', function(snapshot){
    ...
}, function(error) {
    console.error("Something nasty happened", error);
}, function() {
  var downloadURL = uploadTask.snapshot.downloadURL;
  console.log("Done. Enjoy.", downloadURL);
});

但事实证明,Firebase 无法从服务器端上传文件,正如文档中明确指出的那样:

Firebase 存储不包含在服务器端 Firebase npm module中。相反,您可以使用 gcloud Node.js 客户端。

$ npm install --save gcloud

在您的代码中,您可以使用以下方式访问您的存储桶:

var gcloud = require('gcloud')({ ... }); var gcs = gcloud.storage();
var bucket = gcs.bucket('<your-firebase-storage-bucket>');
  • 我们可以在gcloud没有 Google Cloud Platform 帐户的情况下使用吗?如何?

  • 如果没有,为什么可以从客户端将文件上传到 Firebase 存储?

  • 我们不能创建一个从服务器端发出相同请求的库吗?

  • Firebase Storage 是如何与 Google Cloud Platform 连接的?为什么 Firebase 只允许我们从客户端上传图片?


我的第二次尝试是使用该gcloud库,如文档中所述:

var gcloud = require("gcloud");

// The following environment variables are set by app.yaml when running on GAE,
// but will need to be manually set when running locally.
// The storage client is used to communicate with Google Cloud Storage
var storage = gcloud.storage({
  projectId: "em...",
  keyFilename: 'auth.json'
});

storage.createBucket('octocats', function(err, bucket) {

    // Error: 403, accountDisabled
    // The account for the specified project has been disabled.

    // Create a new blob in the bucket and upload the file data.
    var blob = bucket.file("octofez.png");
    var blobStream = blob.createWriteStream();

    blobStream.on('error', function (err) {
        console.error(err);
    });

    blobStream.on('finish', function () {
        var publicUrl = `https://storage.googleapis.com/${bucket.name}/${blob.name}`;
        console.log(publicUrl);
    });

    fs.createReadStream("octofez.png").pipe(blobStream);
});
6个回答

在服务器上使用 firebase 库时,您通常会使用服务帐户进行授权,因为这将授予您对实时数据库的管理员访问权限。您可以使用同一个服务帐号的凭据文件来授权 gcloud

顺便说一句:Firebase 项目本质上也是一个 Google Cloud Platform 项目,您可以在https://console.firebase.google.comhttps://console.cloud.google.comhttps上访问您的 Firebase 项目: //console.developers.google.com 您可以在Firebase 控制台 > 项目设置Cloud Console 控制面板中查看您的项目 ID

使用 gcloud SDK 时,请确保使用 Firebase Storage 正在使用的(已经存在的)相同存储桶。您可以在 Firebase 网络config对象或 Firebase 存储选项卡中找到存储桶名称基本上你的代码应该像这样开始:

var gcloud = require('gcloud');

var storage = gcloud.storage({
  projectId: '<projectID>',
  keyFilename: 'service-account-credentials.json'
});

var bucket = storage.bucket('<projectID>.appspot.com');

...
这真的很有帮助,但仍然存在根本问题:我无法使用gcloud(例如,创建存储桶)上传内容,因为根据此答案,我没有启用计费。同样,为什么gcloud通过客户端访问存储需要计费,而通过客户端 firebase 访问则不需要?谢谢!
2021-03-15 07:49:33
gloud 现在已弃用
2021-03-22 07:49:33
看来您可能需要启用计费,这是真的。我会在内部向团队报告。我们是否应该为存储创建一个 Firebase 特定的服务器 SDK 一直存在争论,目前的共识是“不”。对于计费问题:作为一种解决方法,您可以启用计费并设置零美元限制的预算,以避免收取任何费用。API 本身应该可以免费使用,并且 Firebase Storage 使用的存储桶具有免费配额,因此一切正常。
2021-03-25 07:49:33
对我来说似乎是个问题 - 要启用计费,我需要一个计费帐户。对于结算帐户,我需要在 Google Cloud Platform 上注册,并且在那里注册我需要有业务。所有这些只是为了从服务器端上传 Firebase 存储中的内容。我很好奇他们会说什么。谢谢!
2021-04-08 07:49:33
我在我的问题中添加了另一个片段。
2021-04-14 07:49:33

带有 NodeJS 的管理 SDK 现在支持 Firebase 存储:

https://firebase.google.com/docs/reference/admin/node/admin.storage

// Get the Storage service for the default app
var defaultStorage = firebaseAdmin.storage();
var bucket = defaultStorage.bucket('bucketName');
...
随之而来后bucket()得到REF()?这些似乎有效:bucket.ref() 或 bucket.child('path')
2021-03-21 07:49:33
var bucket = firebaseAdmin.storage().bucket('bucketName');- 这就是诀窍,以下为指导:firebase.google.com/docs/storage/admin/...
2021-04-03 07:49:33
当我尝试这个时,我得到TypeError: defaultStorage is not a function. 使用最新的firebase-adminnpm 库。
2021-04-09 07:49:33

Firebase Admin SDK 允许您直接访问您的 Google Cloud Storage。

有关更多详细信息,请访问Admin Cloud Storage API 简介

var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    storageBucket: "<BUCKET_NAME>.appspot.com"
});

var bucket = admin.storage().bucket();

bucket.upload('Local file to upload, e.g. ./local/path/to/file.txt')
通过使用方法getDownloadURL()
2021-03-22 07:49:33
谢谢你的回答!但是你能分享一个如何使用 getDownloadURL() 的例子吗?再次感谢。
2021-03-30 07:49:33
@Learn2Code 上面的代码会将文件从存储下载到本地。
2021-04-03 07:49:33
const destFilename = 'Local destination for file, e.g. ./local/path/to/file.txt'; const options = { // The path to which the file should be downloaded, e.g. "./file.txt" destination: destFilename, }; bucket.file('Remote file to download, e.g. file.txt').download(options) 参考下载对象
2021-04-08 07:49:33
如何下载存储上的文件?
2021-04-13 07:49:33

我希望它对你有用。我从本地上传了一个文件,然后我使用 UUID 添加了访问令牌,之后我上传到了 firebase 存储。在我生成下载 url 之后。如果我们点击该生成网址,它将自动下载一个文件。

    const keyFilename="./xxxxx.json"; //replace this with api key file
    const projectId = "xxxx" //replace with your project id
    const bucketName = "xx.xx.appspot.com"; //Add your bucket name
    var mime=require('mime-types');
    const { Storage } = require('@google-cloud/storage');
    const uuidv1 = require('uuid/v1');//this for unique id generation

   const gcs = new Storage({
    projectId: projectId,
    keyFilename: './xxxx.json'
     });
    const bucket = gcs.bucket(bucketName);

    const filePath = "./sample.odp";
    const remotePath = "/test/sample.odp";
    const fileMime = mime.lookup(filePath);

//we need to pass those parameters for this function
    var upload = (filePath, remoteFile, fileMime) => {

      let uuid = uuidv1();

      return bucket.upload(filePath, {
            destination: remoteFile,
            uploadType: "media",
            metadata: {
              contentType: fileMime,
              metadata: {
                firebaseStorageDownloadTokens: uuid
              }
            }
          })
          .then((data) => {

              let file = data[0];

              return Promise.resolve("https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent(file.name) + "?alt=media&token=" + uuid);
          });
    }
//This function is for generation download url    
 upload(filePath, remotePath, fileMime).then( downloadURL => {
        console.log(downloadURL);

      });

请注意,不推荐使用 gcloud,请改用 google-cloud。您可以在项目设置->服务帐户中找到 SERVICE_ACCOUNT_KEY_FILE_PATH。

var storage = require('@google-cloud/storage');

var gcs = storage({
    projectId: PROJECT_ID,
    keyFilename: SERVICE_ACCOUNT_KEY_FILE_PATH
  });

// Reference an existing bucket.
var bucket = gcs.bucket(PROJECT_ID + '.appspot.com');

...
类型错误:存储不是函数。您使用的是哪个版本的 @google-cloud/storage?我的是 4.5.0
2021-03-30 07:49:33
按照您的描述进行设置后,如何下载图像?
2021-04-07 07:49:33