Google Cloud Function-为什么存储桶总是返回空文件数组? [英] Google Cloud Function - Why bucket always returns empty array of files?

查看:68
本文介绍了Google Cloud Function-为什么存储桶总是返回空文件数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试访问存储在Firebase存储器中的文件,以将它们的列表返回到我的APK.我做了一个云功能,即使一切似乎都已解决,该功能也无法正常工作.

I'm trying to reach files stored on my Firebase Storage to return a list of them to my APK. I made a cloud function, which is not working, even though when everything seems to be right settle.

index.js

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

const functions = require('firebase-functions');

const images = require('./images.js');

const storage = new Storage({
    projectId: '<my_id>',
    keyFilename: './key.json',
});

const bucket = storage.bucket('<my_bucket>')

exports.getImages = functions.https.onRequest((request, response) => {
    images.getImages(bucket).then(urls => response.send(urls))
})

images.js

module.exports = {
    getImages
}

const query = {
    directory: '/images'
};

async function getImages(bucket) {
    return bucket.getFiles(query).then(files => {
        console.log(files)
        getUrls(files).then(urls => console.log(urls))
            .catch(() => console.error('URLs failure'));
    }).catch(() => console.error('Files failure'));
}

function getUrls(files) {
    const promises = []
    files.forEach(file => promises.push(file.getDownloadURL()))
    return Promise.all(promises);
}

我的Key.json位于我的功能文件夹内

My Key.json is located inside my functions folder

Key.json

{
  "type": "service_account",
  "project_id": "…",
  "private_key_id": "…",
  "private_key": "-----BEGIN PRIVATE KEY——…",
  "client_email": "…",
  "client_id": "…",
  "auth_uri": "…",
  "token_uri": "…",
  "auth_provider_x509_cert_url": "…",
  "client_x509_cert_url": "…"
}

存储规则

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if true
    }
  }
}

执行getImages()函数输出为:

console.log(files): [ [] ]
console.error('Files failure'): Files failure

请问我在做什么错了?

推荐答案

我遇到的第一个也是主要的问题是与Google Cloud Service的连接,这意味着:

First and main problem I had was connecting with my Google Cloud Service, this means:

  1. 我从Firebase管理员生成了一个全新的私钥

  1. 下载的文件并以我的新Key.json

然后是最棘手的部分.根据 Google 的文档

Then comes the trickiest part. According to Google's documentation

您可以将Admin SDK返回的存储桶引用与正式的Google Cloud Storage客户端库结合使用,以上传,下载和修改与Firebase项目关联的存储桶中的内容.请注意,在使用Firebase Admin SDK时,您不必对Google Cloud Storage库进行身份验证. Admin SDK返回的存储桶引用已通过用于初始化Firebase应用程序的凭据进行了身份验证.

You can use the bucket references returned by the Admin SDK in conjunction with the official Google Cloud Storage client libraries to upload, download, and modify content in the buckets associated with your Firebase projects. Note that you do not have to authenticate Google Cloud Storage libraries when using the Firebase Admin SDK. The bucket references returned by the Admin SDK are already authenticated with the credentials used to initialize your Firebase app.

这意味着,如果要在本地运行服务(npm run shell),则需要实例化firebase-admin.

This means, if you are running you service locally (npm run shell), you need to instantiate your firebase-admin.

var serviceAccount = require("./key.json");
var admin = require("firebase-admin");

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://<my_project>.firebaseio.com"
});

然后致电

const bucket = admin.storage().bucket('<my_bucket>.appspot.com')

您将准备访问您的文件.通过部署直接访问Google功能或通过云控制台访问Google功能时,不需要访问存储admin初始化或键本身,例如问题的第一个暴露的index.js,仅将代码转换为类似的

you will be ready to access your files. When accessing your google functions directly through deployment or from cloud console, then accessing your storage wouldn't require an admin initialization or the key itself such as the first exposed index.js on the question, turning the code only into something like

const {Storage} = require('@google-cloud/storage');
...
const storage = new Storage({
    projectId: '<my_id>',
});

const bucket = storage.bucket('<my_bucket>')
...

关于Mayeru所说的话:

您已将目录指定为"/images",但应将其指定为"images/"

you have specified the directory as "/images" but instead it should be "images/"

"images/"可以用于查询prefix参数,而不是directory. 示例展示了其工作原理,例如其参考也是对Google文档的参考.

"images/"could be used for querying prefix parameters, not directory. This example shows how it works, like its reference to google's documentation as well.

以下代码进行了一些许诺调整,并为Android解析了JSON数据,它们的工作原理很像.本地和远程.

The following code, with some promise tweaks and parsing JSON data for Android, works like a charm. Locally and remotely.

index.js

var serviceAccount = require("./key.json");
const functions = require('firebase-functions');

const images = require('./images.js');

var admin = require("firebase-admin");

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://<my_project>.firebaseio.com"
});

const bucket = admin.storage().bucket('<my_bucket>.appspot.com')

exports.getImages = functions.https.onRequest((request, response) => {
    images.getImages(bucket)
        .then(urls => response.status(200).send({ data: { urls } }))
        .catch(err => console.error(err));
})

images.js

module.exports = {
    getImages
}

const query = {
    directory: 'images'
};

function getImages(bucket) {
    return bucket.getFiles(query)
        .then(response => getUrls(response))
        .catch(err => console.error(err));
}

function getUrls(response) {
    const promises = []
    response.forEach( files => {
        files.forEach (file => {
            promises.push(getSignedUrl(file));
        });
    });
    return Promise.all(promises).then(result => getParsedUrls(result));
}

function getSignedUrl(file) {
    return file.getSignedUrl({
        action: 'read',
        expires: '09-01-2019'
    })
}

function getParsedUrls(result) {
    return JSON.stringify(result.map(mediaLink => createMedia(mediaLink)));
}

function createMedia(mediaLink) {
    const reference = {};
    reference.mediaLink = mediaLink[0];
    return reference;
}

这肯定会列出您存储桶中images文件夹下的所有文件,并访问将使用诸如Fresco之类的库呈现的签名的下载URL.最后但并非最不重要的一点是,将显示下载URL,但是要直接在其上发出GET请求,则需要调整存储桶权限.无论如何,这种权限问题"是另一个主题,您可能还会在堆栈溢出的情况下找到如何做的事情.

This will for sure list all the files under images folder from your bucket and access their signed download urls to be rendered with libraries like Fresco. Last, but not least, the download URL will be exposed, but to make a GET request directly on it will require adjustment on your bucket permissions. Anyway, this "permissions thing" is another topic which you might find how to do it also here on stack overflow.

这篇关于Google Cloud Function-为什么存储桶总是返回空文件数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆