问题描述
我正在尝试创建一个 Firebase 函数,它允许我传入一组图像 URL 以创建蒙太奇,将文件上传到 Firebase 存储,然后返回生成的下载 URL。这将从我的应用中调用,因此我使用的是 functions.https.onCall
。
const functions = require("firebase-functions");
const admin = require('firebase-admin');
var gm = require('gm').subClass({imageMagick: true});
admin.initializeApp();
exports.createMontage = functions.https.onCall((data,context) => {
var storageRef = admin.storage().bucket( 'gs://xyz-zyx.appspot.com' );
var createdMontage = storageRef.file('createdMontage.jpg');
function generateMontage(list){
let g = gm()
list.forEach(function(p){
g.montage(p);
})
g.geometry('+81+81')
g.density(5000,5000)
.write(createdMontage,function(err) {
if(!err) console.log("Written montage image.");
});
return true
}
generateMontage(data)
return createdMontage.getDownloadURL();
});
函数 generateMontage()
在 NodeJs 上本地工作(具有本地写入目的地)。
谢谢。
解决方法
看看文档中的这个例子:
https://cloud.google.com/storage/docs/uploading-objects#storage-upload-object-code-sample
2021-01-11 更新
这是一个工作示例。我使用的是常规 Cloud Functions,它的局限性在于 table.name.format=waiting-room
、srcObject
和 dstObject
是常量,但它确实创建了蒙太奇,这是您的目标。
bucketName
还有PROJECT=[[YOUR-PROJECT]]
BILLING=[[YOUR-BILLING]]
REGION=[[YOUR-REGION]]
FUNCTION=[[YOUR-FUNCTION]]
BUCKET=[[YOUR-BUCKET]]
OBJECT=[[YOUR-OBJECT]] # Path from ${BUCKET} root
gcloud projects create ${PROJECT}
gcloud beta billing projects link ${PROJECT} \
--billing-account=${BILLING}
gcloud services enable cloudfunctions.googleapis.com \
--project=${PROJECT}
gcloud services enable cloudbuild.googleapis.com \
--project=${PROJECT}
gcloud functions deploy ${FUNCTION} \
--memory=4gib \
--max-instances=1
--allow-unauthenticated \
--entry-point=montager \
--set-env-vars=BUCKET=${BUCKET},OBJECT=${OBJECT} \
--runtime=nodejs12 \
--trigger-http \
--project=${PROJECT} \
--region=${REGION}
ENDPOINT=$(\
gcloud functions describe ${FUNCTION} \
--project=${PROJECT} \
--region=${REGION} \
--format="value(httpsTrigger.url)")
curl \
--request GET \
${ENDPOINT}
`package.json`:
```JSON
{
"name": "montage","version": "0.0.1","dependencies": {
"@google-cloud/storage": "5.7.1","gm": "^1.23.1"
}
}
:
index.js
,
我从未使用过 'gm',但是,根据它的 npm page,它有一个 SELECT
JSON_LENGTH(comments) as c_total,JSON_LENGTH(likes) as l_total,(c_total+l_total) as total
FROM posts
函数。
所以也许这样的事情可以工作:
toBuffer
但似乎可以更轻松地完成。正如 Methkal Khalawi 评论的那样:
这里是一个 full example on how to use ImageMagic with Functions。虽然他们使用它来模糊图像,但想法是一样的。以及文档中的 here is a tutorial。
,我认为您可以将 gm
模块的输出流通过管道传输到 firebase storage
对象写入流。
const functions = require("firebase-functions");
const admin = require('firebase-admin');
var gm = require('gm').subClass({imageMagick: true});
admin.initializeApp();
exports.createMontage = functions.https.onCall(async (data,context) => {
var storage = admin.storage().bucket( 'gs://xyz-zyx.appspot.com' );
var downloadURL = await new Promise((resolve,reject) => {
let g = gm()
list.forEach(function(p){
g.montage(p);
})
g.geometry('+81+81')
g.density(5000,5000)
.stream((err,stdout,stderr) => {
if (err) {
reject();
}
stdout.pipe(
storage.file('generatedMotent.png).createWriteStream({
metadata: {
contentType: 'image/png',},})
).on('finish',() => {
storage
.file('generatedMotent')
.getSignedUrl({
action: 'read',expires: '03-09-2491',// Non expring public url
})
.then((url) => {
resolve(url);
});
});
})
});
return downloadURL;
});
仅供参考,Firebase Admin SDK 存储对象没有 getDownloadURL()
函数。
您应该从存储对象生成不过期的公共签名 URL。
除此之外,根据这个issue,它应该在一段时间后引起另一个问题。 要解决此问题,您应该使用永久服务帐户初始化 Firebase 应用。
const admin = require('firebase-admin');
const serviceAccount = require('../your-service-account.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),projectId: JSON.parse(process.env.FIREBASE_CONFIG).projectId,databaseURL: JSON.parse(process.env.FIREBASE_CONFIG).databaseURL,storageBucket: JSON.parse(process.env.FIREBASE_CONFIG).storageBucket,});