【问题标题】:Get Public URL from file uploaded with firebase-admin从使用 firebase-admin 上传的文件中获取公共 URL
【发布时间】:2018-04-14 20:01:51
【问题描述】:

我使用 firebase-admin 和 firebase-functions 在 Firebase Storage 中上传文件。

我在存储中有这个规则:

service firebase.storage {
  match /b/{bucket}/o {
    match /images {
      allow read;
      allow write: if false;
    }
  }
}

我想用这个代码获得一个公共 URL:

const config = functions.config().firebase;
const firebase = admin.initializeApp(config);
const bucketRef = firebase.storage();

server.post('/upload', async (req, res) => {

  // UPLOAD FILE

  await stream.on('finish', async () => {
        const fileUrl = bucketRef
          .child(`images/${fileName}`)
          .getDownloadUrl()
          .getResult();
        return res.status(200).send(fileUrl);
      });
});

但是我有这个错误.child is not a function。 如何使用 firebase-admin 获取文件的公共 url?

【问题讨论】:

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


    【解决方案1】:

    这几天我一直在修修补补,终于意识到了

    A) 对桶的正确访问权限是关键:

    service firebase.storage {
      match /b/{bucket}/o {
        match /{allPaths=**} {
          allow read;
          allow write: if request.auth != null;
        }
      }
    }
    

    B) 功能性公共 URL 就在元数据中(经过测试且有效)。注意访问权限。

      const pdfDoc = printer.createPdfKitDocument(docDefinition);
      const pdfFile = admin
          .storage()
          .bucket()
          .file(newId + '.pdf');
    
        pdfDoc.pipe(
          pdfFile.createWriteStream({
            contentType: 'application/pdf',
            public: true,
          })
        );
        pdfDoc.end();
    
        console.log('Get public URL');
        const publicUrl = pdfFile.metadata.mediaLink;
    

    【讨论】:

      【解决方案2】:

      对我有用的是编写这样的 URL:

      https://storage.googleapis.com/<bucketName>/<pathToFile>
      

      示例:https://storage.googleapis.com/mybucket.appspot.com/public/myFile.png

      我是怎么找到的?

      我去了 GCP 控制台,存储。找到上传的文件。点击“复制网址”。

      您可能想先将文件设为公开。我是这样做的:

      const bucket = seFirebaseService.admin().storage().bucket()
      await bucket.file(`public/myFile.png`).makePublic()
      

      【讨论】:

      • 这是正确的方法,它允许您使用 ajax 请求访问文件,例如JSON 数据。
      【解决方案3】:

      从using Cloud Storage documentation上的示例应用代码,你应该可以在上传成功后实现以下代码获取公共下载地址:

      // Create a new blob in the bucket and upload the file data.
      const blob = bucket.file(req.file.originalname);
      const blobStream = blob.createWriteStream();
      
      blobStream.on('finish', () => {
          // The public URL can be used to directly access the file via HTTP.
          const publicUrl = format(`https://storage.googleapis.com/${bucket.name}/${blob.name}`);
          res.status(200).send(publicUrl);
      });
      

      或者,如果您需要可公开访问的下载 URL,请参阅 this answer,它建议使用 Cloud Storage NPM 模块中的 getSignedUrl(),因为 Admin SDK 不直接支持此功能:

      您需要使用getSignedURL 通过 @google-cloud/storage NPM 模块。

      例子:

      const gcs = require('@google-cloud/storage')({keyFilename: 'service-account.json'});
      // ...
      const bucket = gcs.bucket(bucket);
      const file = bucket.file(fileName);
      return file.getSignedUrl({
        action: 'read',
        expires: '03-09-2491'
      }).then(signedUrls => {
        // signedUrls[0] contains the file's public URL
      });
      

      【讨论】:

      • 是@Grimthorr,但匿名用户无权访问该文件。
      • 啊,抱歉,您要改为获取公共访问下载 URL?请参阅 - Get Download URL from file uploaded with Cloud Functions for Firebase 的答案 - 似乎仅使用 Admin SDK 是不可能的。
      • 是的,我知道这种方式,但我不喜欢这种解决方案,因为 url 很长。无论如何,这似乎是唯一的方法。
      • 不幸的是,由于管理 SDK 的限制,我认为这是唯一的途径。我想你可以通过Google's URL shortener API 传递 URL,但这又增加了一步。我已经用另一个人的详细信息更新了我的答案。
      • Admin SDK 在下面使用@google-cloud/storage。 admin.storage().bucket() 返回的存储桶对象来自该包。所以你不必重新初始化 GCS 包。如果您已经使用服务帐户初始化了 admin SDK,您应该能够在从 API 获得的文件引用上调用 getSignedUrl()。
      猜你喜欢
      • 2019-06-20
      • 1970-01-01
      • 2022-07-12
      • 2021-08-12
      • 2020-06-26
      • 1970-01-01
      • 2020-09-11
      • 2017-10-11
      相关资源
      最近更新 更多