如何在Firebase Cloud Function中获取上传的图像链接?

时间:2018-11-28 12:50:19

标签: javascript firebase google-cloud-storage google-cloud-functions

我有一个云功能,可以为每个上载的图像生成一组调整大小的图像。这是通过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在技术上已正确回答了这个问题,但我只想指出一些其他需要做的事情,然后才能起作用。

  1. 看来getSignedUrl()的'expires'参数必须是根据TypeScript的数字。因此,要使其正常工作,我必须传递一个以3589660800000之类的纪元(毫秒)表示的将来日期。

  2. 我需要将凭证传递给admin.initializeApp()才能使用此方法。您需要在Firebase管理员中生成服务帐户密钥。看到这里:https://firebase.google.com/docs/admin/setup?authuser=1

希望这也可以帮助其他人。

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];