Почему мой файл с изображением "запрос" является неполным при сохранении в Google Cloud Storage? - PullRequest
1 голос
/ 26 апреля 2020

Я пытаюсь загрузить изображение с URL-адреса в мое облачное хранилище Google (Firebase). Следующая функция возвращает файл, а последовательная функция возвращает фактический URL-адрес подписанного / загруженного файла в новый файл. После всего этого я обновляю документ в моей базе данных Firestore новым URL. Эта часть работает; функции ждут загрузки (к сожалению, неполного) изображения, и мой документ обновляется с помощью вновь созданного URL файла. Но фактический файл / изображение является неполным. : - (

async function saveToStorage(fileUrl) {
  var storage = admin.storage();
  var urlLib = require("url");
  var pathLib = require("path");
  //Get File Name from provided URL
  var parsed = urlLib.parse(fileUrl);
  var fileName = pathLib.basename(parsed.pathname);

  //Create Storage Reference with new File Name
  var bucket = storage.bucket('gs://myprojectname.appspot.com');
  //Path Folder
  var folderPath = 'data/photos/';
  //Path Folder + File
  var internalFilePath = folderPath + fileName ;
  //Bucket File Ref
  var file = bucket.file(internalFilePath);

  const request = require('request');

  const writeStream = file.createWriteStream({
    metadata: {
      contentType: 'image/jpg'
    }
  });

  return new Promise((resolve, reject) => {
      request.get(fileUrl)
        .pipe(writeStream)
        .on("error", (err) => {
            console.error(`Error occurred`);
            reject();
        })
        .on('finish', () => {
            console.info(`Photo saved`);
            resolve(file); 
        });
  });
}

Изображение, которое сохранено / загружено / передано в мой файл облачного хранилища, выглядит следующим образом: Incomplete Picture

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

Это имеет тот же результат (неполный файл):

return await fetch(fileUrl).then(res => { 

    const contentType = res.headers.get('content-type');
    const writeStream = file.createWriteStream({
        metadata: {
        contentType
        }
    });

    let p = new Promise((resolve, reject) => {
        res.body.pipe(writeStream);
        writeStream.on('finish', function() {
            console.log("Stream finished")
            resolve(file);
        });
        writeStream.on('error', function() {
            reject(new Error("Whoops!"));
        });
    });

    return p.then(
        function(file) {
            console.log('Photo saved');
            return file},
        function(error) {
            console.error(error);
            return;
        });
    });

И прямой возврат потока записывает полный файл, но мой основной код не дожидаясь файла (и мне нужно обработать файл) ..

    return res.body.pipe(writeStream)
      .on('finish', () => {        
        return file;
        console.log('Photo')
      })
      .on('error', err => {
        return console.error(err);
      });

Спасибо за любую помощь в этом!

1 Ответ

1 голос
/ 27 апреля 2020

Так что это код, который, наконец, работал для меня.

 return new Promise((resolve, reject) => {

     const req = request(fileUrl);
     req.pause();
     req.on('response', res => {

        const writeStream = file.createWriteStream({
          metadata: {
            contentType: res.headers['content-type']
          }
        });

        req.pipe(writeStream)
          .on('finish', () => {
            console.log('Photo saved');
            resolve(file);
          })
          .on('error', err => {
            writeStream.end();
            console.error(err);
            reject();
          });

        req.resume();  

     });
     req.on('error', err => console.error(err));   
  });
...