Firebase存储:如何从Node.js上传图像文件

8

求助

我从客户端接收图像,并在文件系统中将其保存到我的服务器上,并处理这个图像,之后需要将其上传到 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);
...

但是我遇到了错误

第一个参数必须是字符串类型或Buffer实例。收到的是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存储: 字符串不与格式 'base64' 匹配:发现无效字符

我已经尝试了很多方法,但是都没有起作用!我做错了什么?

5个回答

26

你可以使用这段代码{{在此处}}。

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"这里是获取您的指南。
  • 用默认存储桶的名称替换<BUCKET_NAME>。您可以在Firebase控制台的存储部分中找到此名称。存储桶名称不能包含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修复此问题。


1
哥们,太感谢了!!你救了我!我一直缺少 firebaseStorageDownloadTokens 键。 - Alex Montoya
1
谢谢,这确实帮了很多忙。 - Tarandeep Singh
这个能通过Cloud Functions完成吗? - Ximena Flores de la Tijera
@XimenaFloresdelaTijera 您是指使用Admin SDK和HTTP触发器一起上传对象吗?如果是的话,当然可以这样做。 - hemauricio
1
我该如何从这段代码中获取下载链接? - Octagod
[错误:ENOENT:没有此文件或目录,stat'/home/my_image.png'] {
errno:-2, code:'ENOENT', syscall:'stat', path:'/home/my_image.png' }
- MbaiMburu

1

对于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


1
也许几个月前将 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)
})

0
使用Firebase-admin和服务帐户,您可以在Firebase中上传文件。
const admin = require('firebase-admin')

var serviceAccount = require("/pathTOServiceAccount.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});

var bucket = admin.storage().bucket('your/firebaseStorage/folderPath')

bucket.upload('pathOfThe/FileIn/Backend', {
  destination: 'path/in/firebase/storage',
  metadata: {
    cacheControl: "public, max-age=315360000", 
    contentType: "image/jpeg"
  }
})

0

可能你的 Node 版本不支持使用 { 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');

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