nodejs загружает pdf в поврежденный файл корзины S3

В настоящее время я использую aws-sdk для загрузки файлов PDF в корзину S3, например:

function uploadFile (filePath, remoteFilename, cb) {
    var fileBuffer = fs.createReadStream(filePath); // ex.: 'temp/longFileName.pdf'
    fileBuffer.on('error', function(err) {
        logger.warn('Failed reading local pdf file');
        cb(err);
    });
    s3.upload({
        Bucket: 'someBucketName',
        Key: remoteFilename,
        Body: fileBuffer
    }, function (error, response) {
        cb(error, { response, remoteFilename });
    });
}

проблема в том, что иногда файл загружается с размером 0B, иногда он загружается с правильным размером, но когда я загружаю его, он поврежден, и, конечно, иногда он правильно загружается и открывается правильно.

Я прочитал файл PDF локально из системного файла, и этот файл PDF правильный.

может ли кто-нибудь помочь мне решить эту проблему?

Обновить

Я создаю PDF-файл, используя pdfkit:

function createPdf (data, cb) {
    var fs = require('fs');
    var PDFDocument = require('pdfkit');
    var filePath = 'temp/longFileName.pdf';
    var pdf = new PDFDocument({
      size: 'LEGAL',
      info: {
        Title: 'Tile of File Here',
        Author: 'Some Author',
      }
    });

    // Write stuff into PDF
    pdf.text('Hello World');

    // Stream contents to a file
    pdf.pipe(
      fs.createWriteStream(filePath)
    )
      .on('finish', function () {
        console.log('PDF closed');
      });

    // Close PDF and write file.
    pdf.end();
    cb(null, {filePath})
}

как только обратный вызов в этой функции вызывается, я вызываю функцию uploadFile:

function doAll (someData, cb) {

    createPdf(someData, function(err, data) {
        if (err) console.log(err)

        uploadFile(data.filePath, function(err,data) {
            if (err) console.log(err)
            console.log('finished')
            cb(null, 'done');
            return;
        })
    })
}

person Bonnard    schedule 22.07.2018    source источник
comment
Поскольку файл находится в temp/, я предполагаю, что файл был только что сохранен. Вы уверены, что он был полностью записан, прежде чем пытаться его открыть? Можем ли мы увидеть, где вы вызываете uploadFile?   -  person Marcos Casagrande    schedule 23.07.2018
comment
@MarcosCasagrande я обновил вопрос с другими функциями   -  person Bonnard    schedule 23.07.2018


Ответы (1)


Проблема в том, что вы вызываете обратный вызов немедленно, а не ждете, пока файл будет полностью записан. Ваша функция обратного вызова должна быть внутри .on('finish')

pdf.pipe(
  fs.createWriteStream('./path/to/file.pdf')
)
.on('finish', function () {
    console.log('PDF closed');
    cb(null, 'finished'); // The callback should e in here
});

// Close PDF and write file.
pdf.end();
person Marcos Casagrande    schedule 23.07.2018
comment
понятно, а как насчет функции s3.upload? он тоже должен быть внутри fileBuffer.on? - person Bonnard; 23.07.2018
comment
Нет-нет, s3.uploader принимает поток, поэтому он не должен находиться внутри какого-либо слушателя. Просто передайте ему поток. - person Marcos Casagrande; 23.07.2018
comment
я имею в виду, должен ли я также ждать, пока у файла тоже будет читаемый поток? потому что я открываю его в функции uploadFile, а затем загружаю на S3... должен ли я ждать, пока он не станет полностью читаемым? - person Bonnard; 23.07.2018
comment
Как только вы вызываете fs.createReadStream, у вас есть действительный readableStream, вам не нужно ждать, просто передайте его s3.uploader, s3 умеет работать с потоками, и он правильно с этим справится. - person Marcos Casagrande; 23.07.2018