Esta respuesta resumirá las opciones para obtener la URL de descarga al cargar un archivo en Google / Firebase Cloud Storage. Hay tres tipos de URL de descarga:
- URL de descarga firmadas, que son temporales y tienen funciones de seguridad
- URL de descarga de token, que son persistentes y tienen características de seguridad
- URL de descarga públicas, que son persistentes y carecen de seguridad
Hay tres formas de obtener una URL de descarga de token. Las otras dos URL de descarga solo tienen una forma de obtenerlas.
Desde Firebase Storage Console
Puede obtener la URL de descarga desde la consola de Firebase Storage:
La URL de descarga se ve así:
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
La primera parte es una ruta estándar a su archivo. Al final está la ficha. Esta URL de descarga es permanente, es decir, no caducará, aunque puede revocarla.
getDownloadURL () desde la interfaz
La documentación nos dice que usemos getDownloadURL()
:
let url = await firebase.storage().ref('Audio/English/United_States-OED-' + i +'/' + $scope.word.word + ".mp3").getDownloadURL();
Esto obtiene la misma URL de descarga que puede obtener de su consola de Firebase Storage. Este método es fácil pero requiere que conozca la ruta a su archivo, que en mi aplicación es de aproximadamente 300 líneas de código, para una estructura de base de datos relativamente simple. Si su base de datos es compleja, esto sería una pesadilla. Y podría cargar archivos desde la interfaz, pero esto expondría sus credenciales a cualquiera que descargue su aplicación. Entonces, para la mayoría de los proyectos, querrá cargar sus archivos desde su back-end de Node o Google Cloud Functions, luego obtenga la URL de descarga y guárdela en su base de datos junto con otros datos sobre su archivo.
getSignedUrl () para URL de descarga temporal
getSignedUrl () es fácil de usar desde un back-end de Node o 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);
}
});
});
});
});
}
Una URL de descarga firmada se ve así:
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
La URL firmada tiene una fecha de vencimiento y una firma larga. La documentación de la línea de comandos gsutil signurl -d dice que las URL firmadas son temporales: el vencimiento predeterminado es una hora y el vencimiento máximo es siete días.
Voy a despotricar aquí que getSignedUrl nunca dice que su URL firmada caducará en una semana. El código de documentación tiene 3-17-2025
como fecha de vencimiento, lo que sugiere que puede establecer los años de vencimiento en el futuro. Mi aplicación funcionó perfectamente y luego se bloqueó una semana después. El mensaje de error decía que las firmas no coincidían, no que la URL de descarga había caducado. Hice varios cambios en mi código y todo funcionó ... hasta que todo falló una semana después. Esto continuó durante más de un mes de frustración.
Haga que su archivo esté disponible públicamente
Puede configurar los permisos en su archivo para lectura pública, como se explica en la documentación . Esto se puede hacer desde el navegador de almacenamiento en la nube o desde su servidor Node. Puede hacer público un archivo o un directorio o toda su base de datos de almacenamiento. Aquí está el código de nodo:
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));
});
El resultado se verá así en su navegador de almacenamiento en la nube:
Cualquiera puede usar la ruta estándar para descargar su archivo:
https://storage.googleapis.com/languagetwo-cd94d.appspot.com/Audio/English/United_States-OED-0/system.mp3
Otra forma de hacer público un archivo es usar el método makePublic () . No he podido hacer que esto funcione, es complicado acertar las rutas del depósito y del archivo.
Una alternativa interesante es utilizar listas de control de acceso . Puede hacer que un archivo esté disponible solo para los usuarios que haya incluido en una lista, o usarlo authenticatedRead
para que el archivo esté disponible para cualquier persona que haya iniciado sesión desde una cuenta de Google. Si hubiera una opción "cualquiera que inicie sesión en mi aplicación usando Firebase Auth", la usaría, ya que limitaría el acceso solo a mis usuarios.
Cree su propia URL de descarga con firebaseStorageDownloadTokens
Varias respuestas describen una propiedad de objeto de Google Storage indocumentada firebaseStorageDownloadTokens
. Con esto, puede decirle a Storage el token que desea usar. Puede generar un token con el uuid
módulo Node. Cuatro líneas de código y puede crear su propia URL de descarga, la misma URL de descarga que obtiene de la consola o getDownloadURL()
. Las cuatro líneas de código son:
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);
Aquí está el código en contexto:
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));
});
Eso no es un error tipográfico, ¡tienes que anidar firebaseStorageDownloadTokens
en capas dobles de metadata:
!
Doug Stevenson señaló que firebaseStorageDownloadTokens
no es una función oficial de Google Cloud Storage. No lo encontrará en ninguna documentación de Google, y no hay ninguna promesa de que lo esté en una versión futura de @google-cloud
. Me gusta firebaseStorageDownloadTokens
porque es la única forma de obtener lo que quiero, pero tiene un "olor" que no es seguro de usar.
¿Por qué No getDownloadURL () de Node?
Como escribió @Clinton, Google debería crear un file.getDownloadURL()
método en @google-cloud/storage
(es decir, su back-end de Node). Quiero subir un archivo desde Google Cloud Functions y obtener la URL de descarga del token.