API-шлюз возвращает поврежденный файл Excel - PullRequest
1 голос
/ 11 марта 2020

Моя конечная точка API возвращает файл Excel, передаваемый с S3. Он работает на локальном компьютере, но при тестировании на API-шлюзе файл поврежден. Вот мой код API:

const downloadContentFromS3 = async function(bucket, file) {
  return new Promise((resolve, reject) => {
    streamFileFromS3(bucket, file, (error, s3buffer) => {
      if (error) return reject(error);
      return resolve(s3buffer);
    });
  });
};

const streamFileFromS3 = async function(bucket, fileName, callback) {
  const params = {
    Bucket: bucket,
    Key: fileName,
  };

  const buffers = [];
  const stream = s3.getObject(params).createReadStream();
  stream.on('data', data => buffers.push(data));
  stream.on('end', () => callback(null, Buffer.concat(buffers)));
  stream.on('error', error => callback(error));
};

downloadExcelFile: async (req, res) => {
  try {
    const fileName = 'myFilename';
    const workbook = await downloadContentFromS3(
      'bucket-name'        
      fileName
    );
    const workbook = xlsx.read(buffer);

    res.setHeader('Content-disposition', `attachment; filename=${fileName}`);
    res.setHeader(
      'Content-type',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    );
    const wbout = xlsx.write(workbook, { bookType: 'xlsx', type: 'buffer' });
    res.status(200).send(Buffer.from(wbout));
  } catch (error) {
    throw new OriolaError(error.message);
  }
},

Что я пробовал до сих пор: Настройте двоичные типы носителей, как показано на рисунке: enter image description here

Кроме того, попытался установить RESPONSE HEADER на Content-Type и Content-Disposition, но безрезультатно. Проблема, кажется, сохраняется. Любые идеи и помощь приветствуются.

РЕДАКТИРОВАТЬ: Я также пытался установить двоичный тип */* в настройках, но это также не помогает.

Ответы [ 2 ]

1 голос
/ 17 марта 2020

API Gateway и Lambda отправляют файлы между собой как base64. Это независимо от того, установлен ли двоичный тип мультимедиа на API-шлюзе, поскольку API-шлюз выполняет преобразование между base64 и двоичным.

S3 getObject получает двоичный файл, но это спорный вопрос для вашей проблемы, так как вы все еще создаете двоичный файл с xlsx.

В настоящий момент вы отправляете двоичные данные, не преобразованные как данные base64.

Все, что вам нужно сделать, это вернуть файл в виде буфера base64 вместо двоичного.

Итак

res.status(200).send(Buffer.from(wbout));

становится

res.status(200).send(Buffer.from(wbout).toString('base64'));
0 голосов
/ 17 марта 2020

https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings.html

Так что либо

  • setup passthrough behaviour и отправьте двоичное тело ответа от вашей функции, как вы уже делаете,
  • или задайте для свойства contentHandling IntegrationResponse resource значение CONVERT_TO_BINARY в дополнение к уже выполненной настройке binaryMediaTypes, а затем отправьте base64 тело ответа.
...