此答案将总结在将文件上传到 Google/Firebase Cloud Storage 时获取下载 URL 的选项。下载 URL 分为三种类型:
- 签名的下载 URL,它们是临时的并且具有安全功能
- 令牌下载 URL,它们是持久的并具有安全功能
- 公共下载 URL,持久且缺乏安全性
获取令牌下载 URL 的方法有 3 种。其他两个下载 URL 只有一种获取方式。
从 Firebase 存储控制台
您可以从 Firebase Storage 控制台获取下载 URL:
下载 URL 如下所示:
https://firebasestorage.googleapis.com/v0/b/languagetwo-cd94d.appspot.com/o/Audio%2FEnglish%2FUnited_States-OED-0%2Fabout.mp3?alt=media&token=489c48b3-23fb-4270-bd85-0a328d2808e5
第一部分是文件的标准路径。最后是令牌。此下载 URL 是永久的,即不会过期,但您可以撤销它。
getDownloadURL() 从前端
文档告诉我们使用getDownloadURL()
:
let url = await firebase.storage().ref('Audio/English/United_States-OED-' + i +'/' + $scope.word.word + ".mp3").getDownloadURL();
这将获得与您可以从 Firebase 存储控制台获得的下载 URL 相同的下载 URL。这种方法很简单,但要求您知道文件的路径,在我的应用程序中,该路径大约有 300 行代码,用于相对简单的数据库结构。如果您的数据库很复杂,这将是一场噩梦。您可以从前端上传文件,但这会将您的凭据暴露给任何下载您的应用程序的人。因此,对于大多数项目,您需要从 Node 后端或 Google Cloud Functions 上传文件,然后获取下载 URL 并将其与有关文件的其他数据一起保存到您的数据库中。
getSignedUrl() 用于临时下载 URL
getSignedUrl()易于从 Node 后端或 Google Cloud Functions 使用:
function oedPromise() {
return new Promise(function(resolve, reject) {
http.get(oedAudioURL, function(response) {
response.pipe(file.createWriteStream(options))
.on('error', function(error) {
console.error(error);
reject(error);
})
.on('finish', function() {
file.getSignedUrl(config, function(err, url) {
if (err) {
console.error(err);
return;
} else {
resolve(url);
}
});
});
});
});
}
签名的下载 URL 如下所示:
https://storage.googleapis.com/languagetwo-cd94d.appspot.com/Audio%2FSpanish%2FLatin_America-Sofia-Female-IBM%2Faqu%C3%AD.mp3?GoogleAccessId=languagetwo-cd94d%40appspot.gserviceaccount.com&Expires=4711305600&Signature=WUmABCZIlUp6eg7dKaBFycuO%2Baz5vOGTl29Je%2BNpselq8JSl7%2BIGG1LnCl0AlrHpxVZLxhk0iiqIejj4Qa6pSMx%2FhuBfZLT2Z%2FQhIzEAoyiZFn8xy%2FrhtymjDcpbDKGZYjmWNONFezMgYekNYHi05EPMoHtiUDsP47xHm3XwW9BcbuW6DaWh2UKrCxERy6cJTJ01H9NK1wCUZSMT0%2BUeNpwTvbRwc4aIqSD3UbXSMQlFMxxWbPvf%2B8Q0nEcaAB1qMKwNhw1ofAxSSaJvUdXeLFNVxsjm2V9HX4Y7OIuWwAxtGedLhgSleOP4ErByvGQCZsoO4nljjF97veil62ilaQ%3D%3D
签名的 URL 具有到期日期和长签名。命令行gsutil signurl -d的文档说签名的 URL 是临时的:默认过期时间为一小时,最长过期时间为 7 天。
我要在这里咆哮,getSignedUrl从来没有说过你的签名 URL 将在一周内过期。文档代码中有3-17-2025
过期日期,提示可以设置未来的过期年份。我的应用程序运行良好,一周后就崩溃了。错误消息说签名不匹配,而不是下载 URL 已过期。我对我的代码进行了各种更改,一切正常……直到一周后一切都崩溃了。这种沮丧持续了一个多月。
使您的文件公开可用
您可以将文件的权限设置为公开阅读,如文档中所述。这可以通过云存储浏览器或您的节点服务器完成。您可以公开一个文件或一个目录或整个存储数据库。这是节点代码:
var webmPromise = new Promise(function(resolve, reject) {
var options = {
destination: ('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.mp3'),
predefinedAcl: 'publicRead',
contentType: 'audio/' + audioType,
};
synthesizeParams.accept = 'audio/webm';
var file = bucket.file('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.webm');
textToSpeech.synthesize(synthesizeParams)
.then(function(audio) {
audio.pipe(file.createWriteStream(options));
})
.then(function() {
console.log("webm audio file written.");
resolve();
})
.catch(error => console.error(error));
});
在您的 Cloud Storage 浏览器中,结果将如下所示:
然后任何人都可以使用标准路径下载您的文件:
https://storage.googleapis.com/languagetwo-cd94d.appspot.com/Audio/English/United_States-OED-0/system.mp3
另一种公开文件的方法是使用方法makePublic()。我无法让它工作,正确获取存储桶和文件路径很棘手。
一个有趣的替代方法是使用访问控制列表。您可以使文件仅对您列入列表的用户可用,或用于authenticatedRead
使从 Google 帐户登录的任何人都可以使用该文件。如果有一个选项“任何使用 Firebase Auth 登录我的应用程序的人”我会使用它,因为它会限制只有我的用户可以访问。
使用 firebaseStorageDownloadTokens 构建您自己的下载 URL
几个答案描述了一个未记录的 Google Storage 对象属性firebaseStorageDownloadTokens
。有了这个,您可以告诉 Storage 您要使用的令牌。uuid
您可以使用Node 模块生成令牌。四行代码,您可以构建自己的下载 URL,与您从控制台或getDownloadURL()
. 四行代码分别是:
const uuidv4 = require('uuid/v4');
const uuid = uuidv4();
metadata: { firebaseStorageDownloadTokens: uuid }
https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.webm') + "?alt=media&token=" + uuid);
这是上下文中的代码:
var webmPromise = new Promise(function(resolve, reject) {
var options = {
destination: ('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.mp3'),
contentType: 'audio/' + audioType,
metadata: {
metadata: {
firebaseStorageDownloadTokens: uuid,
}
}
};
synthesizeParams.accept = 'audio/webm';
var file = bucket.file('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.webm');
textToSpeech.synthesize(synthesizeParams)
.then(function(audio) {
audio.pipe(file.createWriteStream(options));
})
.then(function() {
resolve("https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.webm') + "?alt=media&token=" + uuid);
})
.catch(error => console.error(error));
});
这不是错字——你必须嵌套firebaseStorageDownloadTokens
在metadata:
!
Doug Stevenson 指出,这firebaseStorageDownloadTokens
不是谷歌云存储的官方功能。您不会在任何 Google 文档中找到它,也没有保证它会出现在未来版本的@google-cloud
. 我喜欢firebaseStorageDownloadTokens
,因为这是获得我想要的东西的唯一方法,但它有一种“气味”,使用起来不安全。
为什么没有来自 Node 的 getDownloadURL()?
正如@Clinton 所写,Google 应该在(即您的 Node 后端)中创建file.getDownloadURL()
一个方法。@google-cloud/storage
我想从 Google Cloud Functions 上传文件并获取令牌下载 URL。