我正在尝试访问存储在Firebase存储器中的文件,以将它们的列表返回到我的APK。我做了一个云功能,即使一切似乎都已解决,该功能也无法正常工作。
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
位于我的功能文件夹内
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
请问我在做什么错了?
答案 0 :(得分:2)
我遇到的第一个也是主要的问题是与我的Google Cloud Service连接,这意味着:
下载的文件并以我的新Key.json
然后是最棘手的部分。根据{{3}}的文档
您可以将Admin SDK返回的存储桶引用与正式的Google Cloud Storage客户端库一起使用,以上传,下载和修改与Firebase项目关联的存储桶中的内容。请注意,使用Firebase Admin SDK时不必认证Google Cloud Storage库。 Admin SDK返回的存储桶引用已通过用于初始化Firebase应用程序的凭据进行了身份验证。
这意味着,如果您在本地运行服务(npm run shell
),则需要实例化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
)进行访问,代码只变成类似
const {Storage} = require('@google-cloud/storage');
...
const storage = new Storage({
projectId: '<my_id>',
});
const bucket = storage.bucket('<my_bucket>')
...
关于Mayeru
所说的话:
您已将目录指定为“ / images”,但应将其指定为“ images /”
"images/"
可用于查询prefix
参数,而不是directory
。 cloud console示例展示了它的工作原理,就像Google文档的This一样。
以下代码进行了一些许诺调整,并为Android解析了JSON数据,它们的工作原理很吸引人。本地和远程。
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
文件夹下的所有文件,并访问它们的签名下载URL,这些URL将用Fresco
之类的库呈现。最后但并非最不重要的一点是,下载URL将公开,但是要直接在其上发出GET
请求,则需要调整存储桶权限。无论如何,这种“权限问题”是另一个主题,您可能还会在堆栈溢出的情况下找到如何做的事情。
答案 1 :(得分:1)
日志显示:
[[]] // this is the "files" you retrieved.
Files failure
如您所见,您没有检索任何文件,因此为什么它无法从空数组获取URL的调用失败。
您已将目录指定为“ / images” ,但应将其指定为“ images /”
那应该能够检索正确的文件夹。
此外,nodejs lib documentation上的“文件”对象不支持函数“ getDownloadURL()”。您可能正在寻找getSignedUrl吗?