Как скачать файл из облачного хранилища [Firebase Hosting] - PullRequest
0 голосов
/ 28 мая 2020

Я хотел бы создать веб-приложение с использованием хостинга Firebase.

  1. создать аудиофайл с помощью облачного API преобразования текста в речь
  2. загрузить этот аудиофайл в облачное хранилище
  3. загрузить этот аудиофайл из облачного хранилища в веб-браузер

Я прошел шаги 1 и 2, но у меня проблемы с шагом 3. Я выполнил этот туториал.

https://firebase.google.com/docs/storage/web/download-files

Я развернул свой проект Firebase и протестировал свое приложение. Я мог загрузить аудиофайл в облачное хранилище, но не смог его скачать. Я посмотрел в консоль браузера, но не нашел ни одного сообщения об ошибке. В консоли браузера не было сообщения.

Не могли бы вы мне посоветовать? Заранее спасибо.

Это мой основной. js

'use strict';

// Saves a new message on the Cloud Firestore.
function saveMessage() {
  // Add a new message entry to the Firebase database.
  return firebase.firestore().collection('messages').add({
    text: messageInputElement.value,
    timestamp: firebase.firestore.FieldValue.serverTimestamp()
  }).catch(function(error) {
    console.error('Error writing new message to Firebase Database', error);
  });
}

// Checks that the Firebase SDK has been correctly setup and configured.
function checkSetup() {
  if (!window.firebase || !(firebase.app instanceof Function) || !firebase.app().options) {
    window.alert('You have not configured and imported the Firebase SDK. ' +
        'Make sure you go through the codelab setup instructions and make ' +
        'sure you are running the codelab using `firebase serve`');
  }
}

// Checks that Firebase has been imported.
checkSetup();

// Shortcuts to DOM Elements.
var messageInputElement = document.getElementById('text');
var submitButtonElement = document.getElementById('download');

// Saves message on form submit.
submitButtonElement.addEventListener('click', saveMessage);


// Create a reference from a Google Cloud Storage URI
var storage = firebase.storage();
var gsReference = storage.refFromURL('gs://advan********8.appspot.com/audio/sub.mp3')
gsReference.getDownloadURL().then(function(url) {
  // This can be downloaded directly:
  var xhr = new XMLHttpRequest();
  xhr.responseType = 'blob';
  xhr.onload = function(event) {
    var blob = xhr.response;
  };
  xhr.open('GET', url);
  xhr.send();

}).catch(function(error) {
  // A full list of error codes is available at
  // https://firebase.google.com/docs/storage/web/handle-errors
  switch (error.code) {
    case 'storage/object-not-found':
      console.log('storage/object-not-found')
      break;

    case 'storage/unauthorized':
      console.log('storage/unauthorized')
      break;

    case 'storage/canceled':
      console.log('storage/canceled')
      break;

    case 'storage/unknown':
      console.log('storage/unknown')
      break;
  }  
});

Это индекс. js (Облачные функции)

const functions = require('firebase-functions');
var admin = require("firebase-admin");
admin.initializeApp();
const textToSpeech = require('@google-cloud/text-to-speech');

exports.myFunction = functions.firestore
  .document('messages/{id}')
  .onCreate((change, context) => {
        const client = new textToSpeech.TextToSpeechClient();
        async function quickStart() {

            // The text to synthesize
            const text = 'Hello world';

            // Construct the request
            const request = {
                input: {text: text},
                // Select the language and SSML voice gender (optional)
                voice: {languageCode: 'en-US', ssmlGender: 'NEUTRAL'},
                // select the type of audio encoding
                audioConfig: {audioEncoding: 'MP3'},
            };


            var bucket = admin.storage().bucket('adva********.appspot.com');
            var file = bucket.file('audio/sub.mp3')
            // Create the file metadata
            var metadata = {
                contentType: 'audio/mpeg'
            };

            // Performs the text-to-speech request
            const [response] = await client.synthesizeSpeech(request);
            return await file.save(response.audioContent, metadata)
            .then(() => {
              console.log("File written to Firebase Storage.")
              return;
            })
            .catch((error) => {
              console.error(error);
            });

        }
        quickStart();
    });

Это index. html

<!--./advance/index.html-->
<!doctype html>
<html lang="ja">
   <head>
      <meta name="robots" content="noindex">

      <title>音読アプリ アドバンス</title>
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      <link href="https://fonts.googleapis.com/css?family=M+PLUS+Rounded+1c&display=swap" rel="stylesheet">

      <style> 
            #text {width: 100%; height: 300px; font-family: 'M PLUS Rounded 1c', sans-serif; font-size: 22px;}

            #download {font-family: 'M PLUS Rounded 1c', sans-serif; font-size: 28px;}

      </style>
   </head>

   <body>
      <textarea id="text" class="form-control" name="text" placeholder="ここに英文を入力してください。" maxlength="3000" minlength="1"></textarea>
      <br>
      <div style="text-align:center">
        <input id="download" class="btn btn-primary" type="submit" value="音声をダウンロード">
      </div>

      <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
      <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

      <!-- Import and configure the Firebase SDK -->
      <!-- These scripts are made available when the app is served or deployed on Firebase Hosting -->
      <!-- If you do not want to serve/host your project using Firebase Hosting see https://firebase.google.com/docs/web/setup -->
      <script src="/__/firebase/7.14.3/firebase-app.js"></script>
      <script src="/__/firebase/7.14.3/firebase-auth.js"></script>
      <script src="/__/firebase/7.14.3/firebase-storage.js"></script>
      <script src="/__/firebase/7.14.3/firebase-messaging.js"></script>
      <script src="/__/firebase/7.14.3/firebase-firestore.js"></script>
      <script src="/__/firebase/7.14.3/firebase-performance.js"></script>
      <script src="/__/firebase/7.14.3/firebase-functions.js"></script>
      <script src="/__/firebase/init.js"></script>

      <script src="scripts/main.js"></script>
   </body>
</html>

вкладка Network инструмента разработчика браузера xhr

1 Ответ

1 голос
/ 05 июня 2020

Проблема в том, что вы, вероятно, пытаетесь загрузить файл до того, как файл будет создан вашей облачной функцией, поскольку вы запускаете облачную функцию как триггер события, который автоматически запускается каждый раз при создании документа, но в то же время вы пытаетесь загрузить этот файл на ваш интерфейс. Отсутствие синхронизма создает странное поведение, которое вы наблюдаете.

Чтобы исправить это, вам следует сделать несколько вещей: функция вместо функции, запускаемой событием.

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

exports.myFunction = (req, res) => {
    //you can get the id of the document sent on the request here
    const id=req.body;
    ...
};

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

  • Создайте функцию загрузки и добавьте все ваш код для загрузки в него и добавить синхронности вашим операциям на вашем интерфейсе.

При этом ваш код будет выполняться в правильном порядке, а ваш main. js будет выглядеть так :

// Saves a new message on the Cloud Firestore.
function saveMessage() {
  // Add a new message entry to the Firebase database.
  firebase.firestore().collection('messages').add({
    text: messageInputElement.value,
    timestamp: firebase.firestore.FieldValue.serverTimestamp()
  })
  .then(function(docRef){
    var obj = {  
      method: 'POST',
      body: docRef.id
    };
    //calls function that adds to storage
    fetch("YOUR_FUNTION_URL_HERE", obj).then({
        //actually downloads
        download();
    }).catch(error) {
      console.error('Failed to call cloud function', error);
    });
  }).catch(function(error) {
    console.error('Error writing new message to Firebase Database', error);
  });
}

function download(){
    var storage = firebase.storage();
    var gsReference = storage.refFromURL('gs://advan********8.appspot.com/audio/sub.mp3')
    gsReference.getDownloadURL().then(function(url) {
      // This can be downloaded directly:
      var xhr = new XMLHttpRequest();
      xhr.responseType = 'blob';
      xhr.onload = function(event) {
        var blob = xhr.response;
      };
      xhr.open('GET', url);
      xhr.send();

    }).catch(function(error) {
      // A full list of error codes is available at
      // https://firebase.google.com/docs/storage/web/handle-errors
      switch (error.code) {
        case 'storage/object-not-found':
          console.log('storage/object-not-found')
          break;

        case 'storage/unauthorized':
          console.log('storage/unauthorized')
          break;

        case 'storage/canceled':
          console.log('storage/canceled')
          break;

        case 'storage/unknown':
          console.log('storage/unknown')
          break;
      }  
    });
}

// Checks that Firebase has been imported.
checkSetup();

// Shortcuts to DOM Elements.
var messageInputElement = document.getElementById('text');
var submitButtonElement = document.getElementById('download');

// Saves message on form submit.
submitButtonElement.addEventListener('click', saveMessage);

ПРИМЕЧАНИЕ : Все это не проверено, но это будет хорошей отправной точкой для вас, чтобы начать изменения, необходимые в вашем коде.

...