【问题标题】:Google Cloud Storage `predefinedAcl` and `file.makePublic()` not workingGoogle Cloud Storage `predefinedAcl` 和 `file.makePublic()` 不起作用
【发布时间】:2019-09-21 07:10:00
【问题描述】:

当我从 Firebase Cloud Functions (Google Cloud Functions) 将文件上传到 Firebase Storage (Google Cloud Storage) 时,我正在尝试获取永久下载 URL。

我尝试将predefinedAcl 设置为authenticatedRead 和publicRead。当我的应用程序尝试下载文件时,两者都导致403 (Forbidden) 错误。这是来自CreateWriteStreamOptions 的文档。代码如下:

const {Storage} = require('@google-cloud/storage');
const storage = new Storage({ projectId: 'languagetwo-cd94d' });
const myBucket = storage.bucket('languagetwo-cd94d.appspot.com');

var mp3Promise = new Promise(function(resolve, reject) {
      let options = {
        metadata: {
          contentType: 'audio/mp3',
          public: true
        }
      };

      synthesizeParams.accept = 'audio/mp3';
      var file = myBucket.file('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.mp3');
      textToSpeech.synthesize(synthesizeParams)
      .then(function(audio) {
        audio.pipe(file.createWriteStream(options));
      })
      .then(function() {
        resolve('http://storage.googleapis.com/languagetwo-cd94d.appspot.com/Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.mp3');
      })
      .catch(error => console.error(error));
    });

该代码执行没有错误,将文件写入存储,并将下载 URL 传递给下一个函数。当我尝试使用此 URL 下载文件时:

http://storage.googleapis.com/languagetwo-cd94d.appspot.com/Audio/English/United_States-Allison-Female-IBM/catbirds.mp3

我收到此错误:

<Error>
<Code>AccessDenied</Code>
<Message>Access denied.</Message>
<Details>
Anonymous caller does not have storage.objects.get access to languagetwo-cd94d.appspot.com/Audio/English/United_States-Allison-Female-IBM/catbirds.mp3.
</Details>
</Error>

从我的应用程序下载文件(作为授权用户)我收到403 (Forbidden) 错误消息。

我也试过这个属性,结果一样:

let options = {
        metadata: {
          contentType: 'audio/webm',
          predefinedAcl: 'publicRead'
        }
      };

继续,我尝试了file.makePublic():

const {Storage} = require('@google-cloud/storage');
const storage = new Storage({ projectId: 'languagetwo-cd94d' });
const myBucket = storage.bucket('languagetwo-cd94d.appspot.com');

var mp3Promise = new Promise(function(resolve, reject) {
      let options = {
        metadata: {
          contentType: 'audio/mp3'
        }
      };

      synthesizeParams.accept = 'audio/mp3';
      var file = myBucket.file('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.mp3');
      textToSpeech.synthesize(synthesizeParams)
      .then(function(audio) {
        audio.pipe(file.createWriteStream(options));
      })
      .then(function() {
        file.makePublic()
        .then(function(data) {
          console.log(data)
          resolve('http://storage.googleapis.com/languagetwo-cd94d.appspot.com/Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.mp3');
        })
        .catch(error => console.error(error));
      })
      .catch(error => console.error(error));
    });

这段代码甚至没有执行。它在file.makePublic() 崩溃,错误消息是

{ Error: No such object: languagetwo-cd94d.appspot.com/Audio/English/United_States-Allison-Female-IBM/warblers.mp3

我不确定这个错误是什么意思。我的猜测是file.createWriteStream() 写入了一个文件位置,然后file.makePublic() 找不到该文件位置。

我在云存储浏览器上找到了warblers.mp3 的权限:

【问题讨论】:

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


    【解决方案1】:

    第一个错误是由于对存储桶的访问权限,在链接中您可以 找到身份和Access Management (IAM) 说明,在那里你可以检查角色 以及管理存储桶访问的权限。

    第二个错误可能是第一个错误的结果。

    如果这些信息对您有用,请告诉我。

    【讨论】:

    • 谢谢,文档有很多信息。我为经过身份验证的用户设置了 Firebase 存储规则以读取所有内容:allow read: if request.auth != null;。文档似乎说在上传对象时设置predefinedAcl: 'authenticatedRead' 将对文件执行我为整个数据库设置的操作,即我没有理由在上传时设置此属性。我从经过身份验证的登录中收到 403 错误,所以这不是导致错误的原因。我不知道为什么makePublic() 不起作用它可能会导致同样的错误。
    • 我尝试将我的 Firebase 存储规则更改为公开阅读 allow: read;,我收到了相同的错误消息,Access denied. Anonymous caller does not have storage.objects.get access... 这表明 makePublic() 不会使这些下载 URL 工作,问题不在于文件不公开。
    • 嗨,Thomas,这个问题似乎与存储桶的权限有关,您需要将对象或文件声明为公共存储桶,为此您可以按照链接中的步骤进行操作[1 ],其中描述了您可以公开对象的方式以及如何获取 URL 以共享它。 [1]cloud.google.com/storage/docs/access-control/making-data-public
    • 有趣的是,Google Cloud 上的菜单与 Firebase 上的不同。哪一个是真理的黄金来源?在尝试保存 allUser / reader 角色时,尝试有关我只是得到一个名为“IAM 策略更新失败”“后端错误”的错误的步骤。感觉像地狱一样片状
    【解决方案2】:

    您需要将选项更改为:

    let options = {
        public: true,
        metadata: {
          contentType: 'audio/mp3'           
        }
    };
    

    https://googleapis.dev/nodejs/storage/latest/global.html#CreateWriteStreamOptions

    【讨论】:

      【解决方案3】:

      我一直在为同样的问题苦苦挣扎,最后这里是为我解决的方法:

      const stream = file.createWriteStream(options)
      audio.pipe(stream)
      stream.on('finish', () => {
        // file APIs will now work
      })
      

      问题在于audio.pipe(file.createWriteStream(options)) 创建了一个异步写入文件的流。在您调用 file.makePublic() 的那一刻,无法保证写入流已完成。

      【讨论】:

        猜你喜欢
        • 2012-11-29
        • 1970-01-01
        • 1970-01-01
        • 2019-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多