我有一个云功能,可以为每个上载的图像生成一组调整大小的图像。这是通过onFinalize()
钩触发的。
云功能以调整上传图像的大小:
export const onImageUpload = functions
.runWith({
timeoutSeconds: 120,
memory: '1GB'
})
.storage
.object()
.onFinalize(async object => {
const bucket = admin.storage().bucket(object.bucket)
const filePath = object.name
const fileName = filePath.split('/').pop()
const bucketDir = dirname(filePath)
const workingDir = join(tmpdir(), 'resizes')
const tmpFilePath = join(workingDir, fileName)
if (fileName.includes('resize@') || !object.contentType.includes('image')) {
return false
}
await fs.ensureDir(workingDir)
await bucket.file(filePath).download({
destination: tmpFilePath
})
const sizes = [
500,
1000
]
const uploadPromises = sizes.map(async size => {
const resizeName = `resize@${size}_${fileName}`
const resizePath = join(workingDir, resizeName)
await sharp(tmpFilePath)
.resize(size, null)
.toFile(resizePath)
return bucket.upload(resizePath, {
destination: join(bucketDir, resizeName)
})
})
// I need to now update my Firestore database with the public URL.
// ...but how do I get that here?
await Promise.all(uploadPromises)
return fs.remove(workingDir)
})
这一切都很好,并且可行,但是我还需要以某种方式检索每个图像的公共URL,以便将值写入我的Firestore。
我可以使用getDownloadURL()
在前端执行此操作,但是我不确定如何在Cloud Function中从新生成的图像执行此操作。
正如我所看到的,无论如何这都需要在后端进行,因为我的前端无法知道何时处理图像。
仅适用于客户端:
const storageRef = firebase.storage().ref()
const url = await storageRef.child(`images/${image.name}`).getDownloadURL()
有什么想法吗?
答案(带有警告):
下面的@sergio在技术上已正确回答了这个问题,但我只想指出一些其他需要做的事情,然后才能起作用。
看来getSignedUrl()
的'expires'参数必须是根据TypeScript的数字。因此,要使其正常工作,我必须传递一个以3589660800000
之类的纪元(毫秒)表示的将来日期。
我需要将凭证传递给admin.initializeApp()
才能使用此方法。您需要在Firebase管理员中生成服务帐户密钥。看到这里:https://firebase.google.com/docs/admin/setup?authuser=1
希望这也可以帮助其他人。
答案 0 :(得分:2)
我相信从存储桶上传返回的承诺包含对文件的引用,然后您就可以使用该文件来获取签名的URL。
类似的东西(未经测试):
const data = await bucket.upload(resizePath, { destination: join(bucketDir, resizeName) });
const file = data[0];
const signedUrlData = await file.getSignedUrl({ action: 'read', expires: '03-17-2025'});
const url = signedUrlData[0];