Firebase Storage 从 Node.js 上传图像文件

Firebase Storage upload image file from Node.js

请帮忙

我从客户端接收图像并将其保存在文件系统中的服务器上并处理该图像,之后我需要将其上传到 firebase 存储

我尝试在我的异步函数中从 Node.js 将图像文件上传到 firebase 存储

const path = process.cwd() + '/my_image.jpg';
const file = readFileSync(path);
await firebase.storage().ref().child('my_image.jpg').put(file);
...

但是我有错误

The first argument must be of type string or an instance of Buffer. Received an instance of Uint8Array

好的,我试试二进制格式

const path = process.cwd() + '/my_image.jpg';
const file = readFileSync(path, { encoding: 'base64' });
await firebase.storage().ref().child('my_image.jpg').putString(file, 'base64');
...

我得到错误

Firebase Storage: String does not match format 'base64': Invalid character found"

我已经尝试了很多东西,但没有任何效果! 我做错了什么?

对于 Node js,有一个名为 '@google-cloud/storage

的库
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

const bucket = storage.bucket("my-bucket.appspot.com");
await bucket.upload(
            '/my_image_path.jpg', 
            {
                destination: 'my_uploaded_image.jpg',
                metadata: {
                    cacheControl: "public, max-age=315360000", 
                    contentType: "image/jpeg"
             }
        });

https://www.npmjs.com/package/@google-cloud/storage

您可能需要使用服务帐户密钥对您的 nodejs 客户端进行身份验证。 看到这个 https://cloud.google.com/docs/authentication/getting-started

您可以在此处使用此代码

var admin = require("firebase-admin");
const uuid = require('uuid-v4');

// CHANGE: The path to your service account
var serviceAccount = require("path/to/serviceAccountKey.json");

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

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

var filename = "path/to/image.png"

async function uploadFile() {

  const metadata = {
    metadata: {
      // This line is very important. It's to create a download token.
      firebaseStorageDownloadTokens: uuid()
    },
    contentType: 'image/png',
    cacheControl: 'public, max-age=31536000',
  };

  // Uploads a local file to the bucket
  await bucket.upload(filename, {
    // Support for HTTP requests made with `Accept-Encoding: gzip`
    gzip: true,
    metadata: metadata,
  });

console.log(`${filename} uploaded.`);

}

uploadFile().catch(console.error);

要成功 运行 此代码,您需要:

  • 将 Firebase Admin SDK 添加到您的服务器
  • 安装uuid-v4
  • "path/to/serviceAccountKey.json" 替换为您自己的服务帐户的路径。 Here 是获取指南。
  • <BUCKET_NAME> 替换为默认存储桶的名称。您可以在 Firebase Console 的“存储”部分找到此名称。存储桶名称不得包含 gs:// 或任何其他协议前缀。例如,如果 Firebase 控制台中显示的存储桶 URL 是 gs://bucket-name.appspot.com,则将字符串 bucket-name.appspot.com 传递给 Admin SDK。
  • "path/to/image.png" 替换为您自己的图像的路径。
  • 如果需要,相应地调整 metadata 中的 contentType

特此通知您,每当您使用 Firebase 控制台上传图像时,都会自动生成一个访问令牌。但是,如果您使用任何 Admin SDK 或 gsutil 上传图像,您将需要自己手动生成此访问令牌。这就是 uuid 部分

非常重要的原因

Firebase 支持 表示正在修复此问题,但我认为遇到此问题的任何人都应该这样做,而不是等待 Firebase 修复此问题。

可能您的节点版本不支持带有 { encoding: 'base64' } 选项的 readFileSync 功能。

尝试将缓冲区转换为字符串的原始方法:

const file = readFileSync(path).toString('base64');
// now file is a base64 string
await firebase.storage().ref().child('my_image.jpg').putString(file, 'base64');

也许几个月前无法将 Uint8Array 上传到存储,但现在您可以做到。唯一的问题是您必须通过这种方式在元数据对象中添加内容类型:

const file = new Uint8Array(...)
const metadata = { contentType: 'image/jpeg; charset=utf-8' }
const storageRef = firebase.storage().ref().child('path/to/image.jpg')

await storageRef.put(file, metadata).then((snapshot) => {
  console.log('Uploaded an array!', snapshot)
})