Получить URL-адрес загрузки из файла, загруженного с помощью облачных функций для Firebase

После загрузки файла в Firebase Storage с функциями для Firebase я хотел бы получить URL-адрес загрузки файла.

У меня есть это:

...

return bucket
    .upload(fromFilePath, {destination: toFilePath})
    .then((err, file) => {

        // Get the download url of file

    });

Объектный файл имеет много параметров. Даже один по имени mediaLink, Однако, если я пытаюсь получить доступ к этой ссылке, я получаю эту ошибку:

Анонимные пользователи не имеют доступа к объекту storage.objects.get...

Может кто-нибудь сказать мне, как получить общедоступный URL-адрес загрузки?

Спасибо

27 ответов

Решение

Вам нужно сгенерировать подписанный URL-адрес с помощью getSignedURL через модуль NPM @ google-cloud / storage.

Пример:

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
});

Вам нужно будет инициализировать @google-cloud/storage с учетными данными вашей учетной записи службы в качестве учетных данных приложения по умолчанию будет недостаточно.

ОБНОВЛЕНИЕ: Доступ к Cloud Storage SDK теперь можно получить через Firebase Admin SDK, который действует как обертка вокруг @google-cloud/storage. Единственный способ это сделать, если вы либо:

  1. Инициируйте SDK со специальной учетной записью службы, обычно через второй экземпляр, отличный от используемого по умолчанию.
  2. Или без учетной записи службы, предоставив учетной записи службы App Engine по умолчанию разрешение "signBlob".

В этом ответе будут представлены варианты получения URL-адреса для загрузки при загрузке файла в Google/Firebase Cloud Storage. Существует три типа URL для загрузки:

  1. подписанные URL для загрузки, которые являются временными и имеют функции безопасности
  2. URL загрузки токенов, которые являются постоянными и имеют функции безопасности
  3. общедоступные URL-адреса для загрузки, которые являются постоянными и не имеют безопасности

Есть три способа получить URL для загрузки токена. У двух других URL-адресов для загрузки есть только один способ получить их.

Из консоли хранилища Firebase

Вы можете получить URL для загрузки из консоли Firebase Storage:

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();

Он получает тот же URL-адрес для загрузки, который вы можете получить из консоли Firebase Storage. Этот метод прост, но требует, чтобы вы знали путь к вашему файлу, который в моем приложении составляет около 300 строк кода, для относительно простой структуры базы данных. Если ваша база данных сложна, это будет кошмар. И вы можете загружать файлы из внешнего интерфейса, но это предоставит ваши учетные данные любому, кто загружает ваше приложение. Таким образом, для большинства проектов вы захотите загрузить свои файлы с вашего внутреннего узла или облачных функций Google, затем получите URL-адрес для загрузки и сохраните его в своей базе данных вместе с другими данными о вашем файле.

getSignedUrl() для временных URL загрузки

getSignedUrl() легко использовать из серверной части Node или из облачных функций Google:

  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-адреса являются временными: срок действия по умолчанию составляет один час, а максимальный срок действия - семь дней.

Я собираюсь разглагольствовать здесь, что getSignedUrl никогда не говорит, что ваш подписанный URL истекает через неделю. Код документации имеет 3-17-2025 в качестве даты истечения срока действия, предполагая, что вы можете установить срок годности в будущем. Мое приложение работало отлично, а через неделю рухнуло. В сообщении об ошибке говорится, что подписи не совпадают, а URL-адрес загрузки истек. Я сделал различные изменения в своем коде, и все работало... пока все не рухнуло неделю спустя. Это продолжалось более месяца разочарования.

Сделайте ваш файл общедоступным

Вы можете установить права доступа к вашему файлу для публичного чтения, как описано в документации. Это можно сделать из браузера Cloud Storage или с вашего Node-сервера. Вы можете сделать один файл общедоступным, каталог или всю вашу базу данных хранилища. Вот код узла:

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));
    });

Результат будет выглядеть так в вашем облачном хранилище:

Любой может затем использовать стандартный путь для загрузки вашего файла:

https://storage.googleapis.com/languagetwo-cd94d.appspot.com/Audio/English/United_States-OED-0/system.mp3

Другой способ сделать файл общедоступным - использовать метод makePublic (). Я не смог заставить это работать, сложно сделать правильный путь и путь к файлу.

Интересной альтернативой является использование списков контроля доступа. Вы можете сделать файл доступным только пользователям, которых вы включили в список, или использовать authenticatedRead сделать файл доступным для всех, кто вошел в систему из учетной записи Google. Если бы была опция "любой, кто вошел в мое приложение с помощью Firebase Auth", я бы использовал это, так как это ограничило бы доступ только для моих пользователей.

Создайте свой собственный URL для загрузки с помощью firebaseStorageDownloadTokens

Несколько ответов описывают недокументированное свойство объекта Google Storage firebaseStorageDownloadTokens, При этом вы можете указать Storage токен, который хотите использовать. Вы можете сгенерировать токен с помощью uuid Узловой модуль. Четыре строки кода, и вы можете создать свой собственный URL-адрес для загрузки, тот же 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:!

Дуг Стивенсон отметил, что firebaseStorageDownloadTokens не является официальной функцией Google Cloud Storage. Вы не найдете его ни в одной документации Google, и нет никаких обещаний, что это будет в будущей версии @google-cloud, мне нравится firebaseStorageDownloadTokens потому что это единственный способ получить то, что я хочу, но у него есть "запах", который небезопасно использовать.

Почему нет getDownloadURL() от узла?

Как писал @Clinton, Google должен сделать file.getDownloadURL() метод в @google-cloud/storage (т. е. ваш конец узла). Я хочу загрузить файл из Google Cloud Functions и получить URL-адрес для загрузки токена.

Вот пример того, как указать токен загрузки при загрузке:

const UUID = require("uuid-v4");

const fbId = "<YOUR APP ID>";
const fbKeyFile = "./YOUR_AUTH_FIlE.json";
const gcs = require('@google-cloud/storage')({keyFilename: fbKeyFile});
const bucket = gcs.bucket(`${fbId}.appspot.com`);

var upload = (localFile, remoteFile) => {

  let uuid = UUID();

  return bucket.upload(localFile, {
        destination: remoteFile,
        uploadType: "media",
        metadata: {
          contentType: 'image/png',
          metadata: {
            firebaseStorageDownloadTokens: uuid
          }
        }
      })
      .then((data) => {

          let file = data[0];

          return Promise.resolve("https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent(file.name) + "?alt=media&token=" + uuid);
      });
}

затем позвоните с

upload(localPath, remotePath).then( downloadURL => {
    console.log(downloadURL);
  });

Ключевым моментом здесь является то, что есть metadata объект, вложенный в metadata Опция собственности. настройка firebaseStorageDownloadTokens значение uuid-v4 скажет Cloud Storage использовать его в качестве своего открытого токена авторизации.

Большое спасибо @martemorfosis

Если вы работаете над проектом Firebase, вы можете создавать подписанные URL-адреса в облачной функции, не включая другие библиотеки и не загружая файл учетных данных. Вам просто нужно включить IAM API и добавить роль в существующую учетную запись службы (см. Ниже).

Инициализируйте библиотеку администратора и получите ссылку на файл, как обычно:

import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'

admin.initializeApp(functions.config().firebase)

const myFile = admin.storage().bucket().file('path/to/my/file')

Затем вы создаете подписанный URL с

myFile.getSignedUrl({action: 'read', expires: someDateObj}).then(urls => {
    const signedUrl = urls[0]
})

Убедитесь, что ваша учетная запись службы Firebase имеет достаточные разрешения для запуска этого

  1. Перейдите в консоль API Google и включите API IAM ( https://console.developers.google.com/apis/api/iam.googleapis.com/overview).
  2. В консоли API перейдите в главное меню "IAM & admin" -> "IAM".
  3. Нажмите "Изменить" для роли "Учетная запись службы App Engine по умолчанию".
  4. Нажмите "Добавить другую роль" и добавьте роль "Создатель токена учетной записи службы".
  5. Сохраните и подождите минуту, чтобы изменения распространялись

С ванильной конфигурацией Firebase при первом запуске приведенного выше кода вы получите сообщение об ошибке API Identity and Access Management (IAM) ранее не использовалось в проекте XXXXXX или было отключено., Если вы перейдете по ссылке в сообщении об ошибке и включите IAM API, вы получите еще одну ошибку: для выполнения этой операции на служебной учетной записи my-service-account требуется разрешение iam.serviceAccounts.signBlob. Добавление роли Token Creator устраняет эту вторую проблему с разрешениями.

Я предлагаю использовать опцию predefinedAcl: 'publicRead' при загрузке файла с помощью Cloud Storage NodeJS 1.6.x или +:

const options = {
    destination: yourFileDestination,
    predefinedAcl: 'publicRead'
};

bucket.upload(attachment, options);

Затем получить общедоступный URL-адрес так же просто, как:

bucket.upload(attachment, options).then(result => {
    const file = result[0];
    return file.getMetadata();
}).then(results => {
    const metadata = results[0];
    console.log('metadata=', metadata.mediaLink);
}).catch(error => {
    console.error(error);
});

Это то, что я сейчас использую, это просто и работает без нареканий.

Вам не нужно ничего делать с Google Cloud. Это работает из коробки с Firebase..

// Save the base64 to storage.
const file = admin.storage().bucket('url found on the storage part of firebase').file(`profile_photos/${uid}`);
await file.save(base64Image, {
    metadata: {
      contentType: 'image/jpeg',
    },
    predefinedAcl: 'publicRead'
});
const metaData = await file.getMetadata()
const url = metaData[0].mediaLinkenter

Благодаря последним изменениям в ответе объекта функций вы можете получить все, что вам нужно, чтобы "сшить" вместе URL-адрес загрузки следующим образом:

 const img_url = 'https://firebasestorage.googleapis.com/v0/b/[YOUR BUCKET]/o/'
+ encodeURIComponent(object.name)
+ '?alt=media&token='
+ object.metadata.firebaseStorageDownloadTokens;

console.log('URL',img_url);

Для тех, кто интересуется, куда должен идти файл serviceAccountKey.json Firebase Admin SDK. Просто поместите его в папку функций и разверните как обычно.

Это все еще сбивает меня с толку, почему мы не можем просто получить URL-адрес загрузки из метаданных, как мы делаем в Javascript SDK. Создание URL, срок действия которого истекает, и сохранение его в базе данных нежелательно.

Один метод, который я использую с успехом, состоит в том, чтобы установить значение UUID v4 для ключа с именем firebaseStorageDownloadTokens в метаданных файла после того, как он завершит загрузку и затем сам соберет URL загрузки, следуя структуре, используемой Firebase для генерации этих URL, например:

https://firebasestorage.googleapis.com/v0/b/[BUCKET_NAME]/o/[FILE_PATH]?alt=media&token=[THE_TOKEN_YOU_CREATED]

Я не знаю, насколько "безопасно" использовать этот метод (учитывая, что Firebase может изменить способ генерации URL-адресов для загрузки в будущем), но его легко реализовать.

Извините, но я не могу оставить комментарий к вашему вопросу выше из-за отсутствия репутации, поэтому я включу его в этот ответ.

Сделайте, как указано выше, сгенерировав подписанный URL-адрес, но вместо использования service-account.json я думаю, что вы должны использовать serviceAccountKey.json, который вы можете сгенерировать в (замените YOURPROJECTID соответствующим образом)

https://console.firebase.google.com/project/YOURPROJECTID/settings/serviceaccounts/adminsdk

Пример:

const gcs = require('@google-cloud/storage')({keyFilename: 'serviceAccountKey.json'});
// ...
const bucket = gcs.bucket(bucket);
// ...
return bucket.upload(tempLocalFile, {
        destination: filePath,
        metadata: {
          contentType: 'image/jpeg'
        }
      })
      .then((data) => {
        let file = data[0]
        file.getSignedUrl({
          action: 'read',
          expires: '03-17-2025'
        }, function(err, url) {
          if (err) {
            console.error(err);
            return;
          }

          // handle url 
        })

Я не могу комментировать ответ, который дал Джеймс Дэниелс, но я думаю, что это очень важно прочитать.

Выдача подписанного URL-адреса Как он это сделал, во многих случаях кажется довольно плохим и, возможно, опасным. Согласно документации Firebase, срок действия подписанного URL истекает через некоторое время, поэтому добавление его в базу данных приведет к появлению пустого URL через определенный промежуток времени.

Возможно, что там неправильно истолкована документация, а срок действия подписанного URL не истекает, что может привести к проблемам с безопасностью. Ключ кажется одинаковым для каждого загруженного файла. Это означает, что, получив URL-адрес одного файла, кто-то может легко получить доступ к файлам, к которым он не имеет доступа, просто зная их имена.

Если бы я не понял этого, я бы хотел исправить. В противном случае кто-то должен, вероятно, обновить вышеуказанное решение. Если я могу ошибаться там

FireBaser здесь

В версию 11.10 Admin SDK для Node.js добавленgetDownloadURL()метод. Пример его использования можно найти в документации по получению общего URL-адреса :

      const { getStorage, getDownloadURL } = require('firebase-admin/storage');

const fileRef = getStorage().bucket("my-bucket").file("my-file");
const downloadURL= await getDownloadURL(fileRef);

Использовать file.publicUrl()

Асинхронный/ожидание

      const bucket = storage.bucket('bucket-name');
const uploadResponse = await bucket.upload('image-name.jpg');
const downloadUrl = uploadResponse[0].publicUrl();

Перезвонить

      const bucket = storage.bucket('bucket-name');
bucket.upload('image-name.jpg', (err, file) => {
  if(!file) {
    throw err;
  }

  const downloadUrl = file.publicUrl();
})

The downloadUrlбудет "https://storage.googleapis.com/bucket-name/image-name.jpg".

Обратите внимание, что для того, чтобы приведенный выше код работал, вы должны сделать корзину или файл общедоступными. Для этого следуйте инструкциям здесь https://cloud.google.com/storage/docs/access-control/making-data-public . Кроме того, я импортировал @google-cloud/storagepackage напрямую, а не через Firebase SDK.

Если вы используете предопределенное значение списков управления доступом publicRead, вы можете загрузить файл и получить к нему доступ с очень простой структурой URL:

// Upload to GCS
const opts: UploadOptions = {
  gzip: true,
  destination: dest, // 'someFolder/image.jpg'
  predefinedAcl: 'publicRead',
  public: true
};
return bucket.upload(imagePath, opts);

Затем вы можете построить URL так:

const storageRoot = 'https://storage.googleapis.com/';
const bucketName = 'myapp.appspot.com/'; // CHANGE TO YOUR BUCKET NAME
const downloadUrl = storageRoot + bucketName + encodeURIComponent(dest);

Ответ Laurent работает лучше всего

const uploadOptions: UploadOptions = {
    public: true
};

const bucket = admin.storage().bucket();
[ffile] = await bucket.upload(oPath, uploadOptions);
ffile.metadata.mediaLink // this is what you need

У меня была та же проблема, однако я смотрел на код примера функции firebase вместо README. И ответы в этой теме тоже не помогли...

Вы можете избежать передачи файла конфигурации, выполнив следующие действия:

Перейдите в Cloud Console вашего проекта > IAM & admin> IAM, найдите учетную запись службы App Engine по умолчанию и добавьте роль создателя токена учетной записи службы к этому участнику. Это позволит вашему приложению создавать подписанные общедоступные URL-адреса для изображений.

источник: функция автоматического создания миниатюр README

Ваша роль для движка приложения должна выглядеть следующим образом:

Облачная Консоль

Я видел это в документации по хранилищу администратора

const options = {
  version: 'v4',
  action: 'read',
  expires: Date.now() + 15 * 60 * 1000, // 15 minutes
};

// Get a v4 signed URL for reading the file
const [url] = await storage
  .bucket(bucketName)
  .file(filename)
  .getSignedUrl(options);

console.log('Generated GET signed URL:');
console.log(url);
console.log('You can use this URL with any user agent, for example:');
console.log(`curl '${url}'`);

Это работает, если вам просто нужен публичный файл с простым URL. Обратите внимание, что это может отменить ваши правила хранения Firebase.

bucket.upload(file, function(err, file) {
    if (!err) {
      //Make the file public
      file.acl.add({
      entity: 'allUsers',
      role: gcs.acl.READER_ROLE
      }, function(err, aclObject) {
          if (!err) {
              var URL = "https://storage.googleapis.com/[your bucket name]/" + file.id;
              console.log(URL);
          } else {
              console.log("Failed to set permissions: " + err);
          }
      });  
    } else {
        console.log("Upload failed: " + err);
    }
});

Без signedURL() с помощью makePublic()

const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp()
var bucket = admin.storage().bucket();

// --- [Above] for admin related operations, [Below] for making a public url from a GCS uploaded object

const { Storage } = require('@google-cloud/storage');
const storage = new Storage();

exports.testDlUrl = functions.storage.object().onFinalize(async (objMetadata) => {
    console.log('bucket, file', objMetadata.bucket + ' ' + objMetadata.name.split('/').pop()); // assuming file is in folder
    return storage.bucket(objMetadata.bucket).file(objMetadata.name).makePublic().then(function (data) {
        return admin.firestore().collection('publicUrl').doc().set({ publicUrl: 'https://storage.googleapis.com/' + objMetadata.bucket + '/' + objMetadata.name }).then(writeResult => {
            return console.log('publicUrl', writeResult);
        });
    });
});

Для тех, кто использует Firebase SDK иadmin.initializeApp:

1 - Сгенерируйте закрытый ключ и поместите в папку /functions.

2 - Настройте ваш код следующим образом:

const serviceAccount = require('../../serviceAccountKey.json');
try { admin.initializeApp(Object.assign(functions.config().firebase, { credential: admin.credential.cert(serviceAccount) })); } catch (e) {}

Документация

Try/catch заключается в том, что я использую index.js, который импортирует другие файлы и создает одну функцию для каждого файла. Если вы используете один файл index.js со всеми функциями, вы должны admin.initializeApp(Object.assign(functions.config().firebase, { credential: admin.credential.cert(serviceAccount) }));,

Это лучшее, что я придумал. Это избыточно, но единственное разумное решение, которое сработало для меня.

await bucket.upload(localFilePath, {destination: uploadPath, public: true});
const f = await bucket.file(uploadPath)
const meta = await f.getMetadata()
console.log(meta[0].mediaLink)

Начиная с Firebase 6.0.0 я мог получить доступ к хранилищу напрямую с помощью администратора:

const bucket = admin.storage().bucket();

Поэтому мне не нужно было добавлять служебную учетную запись. Затем установка UUID, как указано выше, сработала для получения URL-адреса firebase.

тлдр; Загрузка большого двоичного объекта и получение URL-адреса изображения:

      const file = storage.bucket().file(`images/${imageName}.jpeg`)

await file.save(image)

const imgUrl = file.metadata.mediaLink

Для тех, кто пытается использовать параметр токена для совместного использования файла и хотел бы использовать команду gsutil, вот как я это сделал:

Сначала вам нужно пройти аутентификацию, запустив: gcloud auth

Затем запустите:

gsutil setmeta -h "x-goog-meta-firebaseStorageDownloadTokens:$FILE_TOKEN" gs://$FIREBASE_REPO/$FILE_NAME

Затем вы можете скачать файл по следующей ссылке:

https://firebasestorage.googleapis.com/v0/b/$FIREBASE_REPO/o/$FILE_NAME?alt=media&token=$FILE_TOKEN

Из Admin SDK вы не можете получить токен загрузки, сгенерированный Firebase для загруженного файла, но вы можете установить этот токен при загрузке, добавив его в метаданные.

Для тех, кто работает над Python SDK. Вот как это сделать:

      from firebase_admin import storage
from uuid import uuid4

bucket = storage.bucket()
blob = bucket.blob(path_to_file)
token = str(uuid4()) # Random ID

blob.metadata = {
        "firebaseStorageDownloadTokens": token
    }
blob.upload_from_file(file)

Теперь вы загрузили файл и получили токен URL. Теперь вы можете сохранить токен (или даже полный URL-адрес загрузки) в свою базу данных (например, Firestore) и отправить его клиенту при запросе файла, а затем заставить клиента самостоятельно получить файл.

Полный URL загрузки выглядит следующим образом:

      https://firebasestorage.googleapis.com/v0/b/{bucket_name}/o/{file_name}?alt=media&token={token}

Я уже публикую свой ответ... в URL-адресе ниже, где вы можете получить полный код с решением

Как загрузить изображение (строку) в кодировке base64 непосредственно в корзину Google Cloud Storage с помощью Node.js?

const uuidv4 = require('uuid/v4');
const uuid = uuidv4();

    const os = require('os')
    const path = require('path')
    const cors = require('cors')({ origin: true })
    const Busboy = require('busboy')
    const fs = require('fs')
    var admin = require("firebase-admin");


    var serviceAccount = {
        "type": "service_account",
        "project_id": "xxxxxx",
        "private_key_id": "xxxxxx",
        "private_key": "-----BEGIN PRIVATE KEY-----\jr5x+4AvctKLonBafg\nElTg3Cj7pAEbUfIO9I44zZ8=\n-----END PRIVATE KEY-----\n",
        "client_email": "xxxx@xxxx.iam.gserviceaccount.com",
        "client_id": "xxxxxxxx",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-5rmdm%40xxxxx.iam.gserviceaccount.com"
      }

    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        storageBucket: "xxxxx-xxxx" // use your storage bucket name
    });


    const app = express();
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
app.post('/uploadFile', (req, response) => {
    response.set('Access-Control-Allow-Origin', '*');
    const busboy = new Busboy({ headers: req.headers })
    let uploadData = null
    busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
        const filepath = path.join(os.tmpdir(), filename)
        uploadData = { file: filepath, type: mimetype }
        console.log("-------------->>",filepath)
        file.pipe(fs.createWriteStream(filepath))
      })

      busboy.on('finish', () => {
        const bucket = admin.storage().bucket();
        bucket.upload(uploadData.file, {
            uploadType: 'media',
            metadata: {
              metadata: { firebaseStorageDownloadTokens: uuid,
                contentType: uploadData.type,
              },
            },
          })

          .catch(err => {
            res.status(500).json({
              error: err,
            })
          })
      })
      busboy.end(req.rawBody)
   });




exports.widgets = functions.https.onRequest(app);

Если вы получаете сообщение об ошибке:

Google Cloud Functions: require (â € ¦) не является функцией

попробуй это:

const {Storage} = require('@google-cloud/storage');
const storage = new Storage({keyFilename: 'service-account-key.json'});
const bucket = storage.bucket(object.bucket);
const file = bucket.file(filePath);
.....
Другие вопросы по тегам