使用 Firebase 函数获取上传到 Firebase 存储的 pdf 的签名下载 URL
Posted
技术标签:
【中文标题】使用 Firebase 函数获取上传到 Firebase 存储的 pdf 的签名下载 URL【英文标题】:Get Signed Download URL of pdf uploaded to Firebase Storage with Firebase Functions 【发布时间】:2018-10-09 21:00:24 【问题描述】:在谷歌上花费了很多时间和无数小时的文档阅读之后,我来到这里提出这个问题,因为我没有取得任何进展。
我正在尝试使用 firebase 函数将文件上传到 Firebase 存储,然后在 firebase 函数完成时获取下载 url 以发回。
首先,我在index.js
的顶部添加了firebase-admin
和@google-cloud/storage
。并初始化它们。
const storage = require('@google-cloud/storage');
const functions = require('firebase-functions');
const admin = require("firebase-admin");
admin.initializeApp(
credential: admin.credential.cert(
// removed for security
// This block was provided by Firebase Admin SDK
// under service accounts in settings of Firebase.
),
databaseUrl: //removed for security,
storageBucket: //removed for security
);
最后,我的函数创建了一个 firebase 数据库记录,生成一个 PDF 并将该文件存储在 firebase 存储中,然后应该返回一个有效的 url 来获取 pdf。
exports.createInvoice = functions.https.onRequest((req, res) =>
cors(req, res, () =>
if(req.method == 'POST')
generateInvoiceNumber().then((number) =>
req.body.number = number.number;
req.body.created = admin.database.ServerValue.TIMESTAMP;
var total = 0;
var items = req.body.items;
for (var i = items.length - 1; i >= 0; i--)
total = total + (items[i].cost * items[i].qty);
req.body.total = total.toFixed(2);
admin.database().ref('invoices').push(req.body).then(function(response)
var html = // removed for brevity;
var file = admin.storage().bucket().file('/tmp/invoice-'+number.number+'.pdf');
htmlPdf.create(html).toStream(function(err, stream)
stream.pipe(file.createWriteStream());
//stream.on('finish', function()
const config =
action: 'read',
expires: '03-09-2491',
contentType: 'application/pdf'
;
admin.storage().bucket().file('tmp/invoice-'+number.number+'.pdf').getSignedUrl(config).then(signedUrls =>
res.status(200).send(signedUrls);
)
//);
);
);
).catch(error =>
res.status(500).send(error);
)
else
res.status(405).send('Method Not Allowed');
);
);
唯一不能正常工作的部分是在我的函数末尾附近返回的 URL。
admin.storage().bucket().file('tmp/invoice-'+number.number+'.pdf').getSignedUrl(config).then(signedUrls =>
res.status(200).send(signedUrls);
);
当我尝试在浏览器中访问返回的 url 时,出现以下错误。
The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.
【问题讨论】:
我知道这个问题之前已经在 *** 上被问过,因为我已经在这个平台上尝试了很多答案。请不要标记为重复,因为它们不需要相同的答案,很明显,因为我以前尝试过它们。 您是否需要使用所有这些属性来初始化管理 SDK,或者您可以只采用 Cloud Functions 为您的项目提供的默认配置吗?除非您需要在项目之外进行访问,否则您可以不带参数进行初始化以获取所有默认值。 【参考方案1】:嗯,我正在做的事情是因为我正在使用类似的东西,我发现您在元数据中寻找的关键是 mediaLink。这是我的代码示例。
admin.storage().bucket().file(`home/home-carousel/$filename`).save(file, (data) =>
if(!data)
res(admin.storage().bucket().file(`home/home-carousel/$filename`).getMetadata().mediaLink)
)
res() 是你想要的部分!
编辑:getMetadata 返回一个您必须解决才能获取元数据的承诺,如果您不这样做,您的 mediaLink 将是未定义的。而且,有几个从 promise 传回的参数,像数组一样访问它们,我提供了一个代码示例。
const saveLocation = storage.bucket('salesportal-8b7ef.appspot.com').file(`home/home-carousel/$webPFileName`)
saveLocation.save(data, (stuff) =>
if(!stuff)
saveLocation.makePublic().then( () =>
saveLocation.getMetadata()
.then( (meta) =>
metadata = meta[0]
admin.firestore().collection("Pages").doc("home-carousel").set( homeCarousel : [`$filename`] : webPUrl : `$metadata.mediaLink` , merge: true).then(
() =>
resolve()
)
)
)
【讨论】:
以上是关于使用 Firebase 函数获取上传到 Firebase 存储的 pdf 的签名下载 URL的主要内容,如果未能解决你的问题,请参考以下文章
Firebase Phone Auth 在发布版本中不起作用
Firebase 云函数中的 Object.values()