Получение ESOCKETTIMEOUT, ECONNRESET или сокета зависает с большим файлом при потоковой передаче в GCP через file.createWriteStream()

При попытке загрузить большой файл ( > 50 МБ) в Google Cloud Storage с помощью облачной функции Google я воспользуюсь этими исключениями в зависимости от параметров, которые я установил:

  • При установке опции запроса "навсегда: false" я получаю: Ошибка: сокет повесил трубку
  • При установке опции запроса "возобновить: истина" я получаю: Ошибка: напишите ECONNRESET
  • При установке опции запроса "возобновить: false" я получаю: Ошибка: ESOCKETTIMEDOUT с возобновлением: false

Вот код, который я использую:

function uploadFile(bucketName, filename, data) {
  console.log("Starting uploading blob...");
  const Storage = require('@google-cloud/storage');

  console.log("Creating client...");
  const storage = new Storage();
  storage.interceptors.push({
      request: function(reqOpts) {
        reqOpts.forever = false;
        return reqOpts
      }
    });

  console.log("Getting bucket " + bucketName + "...");
  const bucket = storage.bucket(bucketName);
  console.log("Creating file " + filename + "...");
  const file = bucket.file(filename);
  console.log("Creating write stream...");

  var writeStream = file.createWriteStream({
    metadata: {
      contentType: 'plain/text'
    },
    resumable: false
  });

  writeStream.on('error', function(e) { console.error("An error occurred : " + e); });
  writeStream.on('finish', function() { console.log("Success"); });

  console.log("Initializing Streaming...");
  var bufferStream = new stream.PassThrough();
  bufferStream.end(data);
  bufferStream.pipe(writeStream);
}

Есть ли что-то, что мне не хватает?

Ответ 1

Я исправил его проблему, используя запрос lib (2.83.0) вместо "request-prom". Вот упрощенный код, который я использую:

const request = require('request').defaults({
    timeout: 500000,
    gzip: true,
    forever: false,
    pool: {
        maxSockets: Infinity
    }
});
const Storage = require('@google-cloud/storage');
const storage = new Storage();
storage.interceptors.push({
    request: function(reqOpts) {
        reqOpts.forever = false;
        return reqOpts
    }
});

/**
 * HTTP Cloud Function.
 *
 * @param {Object} req Cloud Function request context.
 * @param {Object} res Cloud Function response context.
 */
exports.exportToGCS = function exportToGCS(req, res) {
   var bucket = req.body.bucket;
   var fileName = req.body.fileName;

    try {
        console.log("Getting bucket " + bucket + "...");
        var bucket = storage.bucket(bucket);
        console.log("Creating file " + fileName + "...");
        const file = bucket.file(fileName);
        console.log("Creating writeStream...");
        var writeStream = createWriteStream(file);
        // Get the stream from a request to send out to GCS
        var options = createRequest();
        request
            .get(options)
            .pipe(writeStream);
        console.log("Streaming to Storage...");
        res.send("The export has been successfully initialized");
    } catch (e) {
        console.error(e.message, e.name);
        res.status(500).send("An error occurred during the export initialization");
    }
};

// Initialize the PDF write stream
function createWriteStream(file) {
    var writeStream = file.createWriteStream({
        metadata: {
            //metadata you want to set
        }
    });
    writeStream .on('error', function(e) { console.error("An error occurred : " + e); });
    writeStream .on('finish', function() { console.log("Export  completed"); });
    return writeStream ;
}

Надеюсь, что это поможет!