【问题标题】:How to get public download link within a firebase storage trigger function: "onFinalize"?如何在firebase存储触发函数中获取公共下载链接:“onFinalize”?
【发布时间】:2019-04-10 21:49:14
【问题描述】:

我正在写一个firebase云函数,将最近上传的文件的下载链接记录到实时数据库中:

exports.recordImage = functions.storage.object().onFinalize((object) => {

});

“object”让我可以访问两个变量“selfLink”和“mediaLink”,但在浏览器中输入这两个变量时,它们都会返回以下内容:

Anonymous caller does not have storage.objects.get access to ... {filename}

因此,它们不是公共链接。如何在此触发函数中获取公共下载链接?

【问题讨论】:

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


    【解决方案1】:

    *使用此功能:

    function mediaLinkToDownloadableUrl(object) {
            var firstPartUrl = object.mediaLink.split("?")[0] // 'https://www.googleapis.com/download/storage/v1/b/abcbucket.appspot.com/o/songs%2Fsong1.mp3.mp3'
            var secondPartUrl = object.mediaLink.split("?")[1] // 'generation=123445678912345&alt=media'
    
            firstPartUrl = firstPartUrl.replace("https://www.googleapis.com/download/storage", "https://firebasestorage.googleapis.com")
            firstPartUrl = firstPartUrl.replace("v1", "v0")
    
            firstPartUrl += "?" + secondPartUrl.split("&")[1]; // 'alt=media'
            firstPartUrl += "&token=" + object.metadata.firebaseStorageDownloadTokens
    
            return firstPartUrl
        }
    

    这就是你的代码的样子:

    export const onAddSong = functions.storage.object().onFinalize((object) => {
    
        console.log("object: ", object);
    
        var url = mediaLinkToDownloadableUrl(object);
    
        //do anything with url, like send via email or save it in your database in playlist table 
        //in my case I'm saving it in mongodb database
    
        return new playlistModel({
            name: storyName,
            mp3Url: url,
            ownerEmail: ownerEmail
        })
        .save() // I'm doing nothing on save complete
        .catch(e => {
            console.log(e) // log if error occur in database write
        })
    
    })
    

    *我已经在 mp3 文件上测试过这种方法,我确信它适用于所有类型的文件,但如果它不适合你,只需转到 firebase 存储仪表板打开任何文件并复制下载 url,然后尝试在您的代码中生成相同的网址,并尽可能编辑此答案

    【讨论】:

    • 很好的答案。你拯救了我的一天。虽然我相信下载 url 应该可以直接从对象属性中获得(特别是如果它可以构造)
    【解决方案2】:

    您必须使用异步getSignedUrl() 方法,请参阅Cloud Storage Node.js 库的文档:https://cloud.google.com/nodejs/docs/reference/storage/2.0.x/File#getSignedUrl

    所以下面的代码应该可以解决问题:

    .....
    const defaultStorage = admin.storage();
    .....
    
    exports.recordImage = functions.storage.object().onFinalize(object => {    
      const bucket = defaultStorage.bucket();
      const file = bucket.file(object.name);
    
      const options = {
        action: 'read',
        expires: '03-17-2025'
      };
    
      // Get a signed URL for the file
      return file
        .getSignedUrl(options)
        .then(results => {
          const url = results[0];
    
          console.log(`The signed url for ${filename} is ${url}.`);
          return true;
        })
    
    });
    

    请注意,为了使用 getSignedUrl() 方法,您需要使用专用服务帐户的凭据初始化 Admin SDK,请参阅此 SO Question & Answer firebase function get download url after successfully save image to firebase cloud storage

    【讨论】:

    • @Osama 嗨,您有时间尝试建议的答案吗?
    • 嗨,是的,我试过了,但失败了。经过长时间的调查,我发现您提供的代码中有一个小错误:const file = bucket.file(object.bucket + '/' + object.name);应该是:const file = bucket.file(object.name);所以,只是对象名称。您可以编辑它,以便其他人受益吗?谢谢。
    • 感谢您指出这个错误,我已经编辑了答案。如果您认为我的回答有帮助,您可以投票并接受它,请参阅stackoverflow.com/help/someone-answers。谢谢。
    • @PascalLamers 您在选项对象中设置了过期日期,请查看答案中的代码。
    • @PascalLamers 确实是的(除非你知道不朽的秘密;-))
    猜你喜欢
    • 2020-03-08
    • 2021-11-29
    • 2021-07-25
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 2021-10-01
    • 2021-03-30
    相关资源
    最近更新 更多