【问题标题】:API gateway returning corrupted excel fileAPI 网关返回损坏的 Excel 文件
【发布时间】:2020-06-23 08:52:01
【问题描述】:

我的 API 端点返回一个从 S3 流式传输的 excel 文件。它适用于本地,但在 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);
  }
},

到目前为止我已经尝试过: 如图所示设置二进制媒体类型:

另外尝试将 RESPONSE HEADER 设置为 Content-Type 和 Content-Disposition 但无济于事。问题似乎仍然存在。任何想法和帮助表示赞赏。

编辑:我也尝试在设置中设置二进制类型*/*,但这也无济于事。

【问题讨论】:

  • base64 怎么样?也许它是以 base64 编码下载的?
  • 我怎样才能使它正确呢?提供可以实现此目的的标头选项。

标签: node.js amazon-web-services express aws-lambda aws-api-gateway


【解决方案1】:

API Gateway 和 Lambda 在它们之间以 base64 格式发送文件。这与您是否在 API Gateway 上设置二进制媒体类型无关,因为 API Gateway 会在 base64 和二进制之间进行转换。

S3 getObject 获取一个二进制文件,但这对于您的问题尚无定论,因为您仍在使用 xlsx 创建二进制文件。

您目前正在做的是发送未转换为 base64 数据的二进制数据。

您需要做的就是将文件作为 base64 缓冲区而不是二进制缓冲区返回。

所以

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

变成

res.status(200).send(Buffer.from(wbout).toString('base64'));

【讨论】:

    【解决方案2】:

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

    所以要么

    • 设置 passthrough behaviour 并从您的函数中发送二进制响应正文,就像您已经在做的那样,
    • 或将IntegrationResponse resourcecontentHandling属性设置为CONVERT_TO_BINARY,除了binaryMediaTypes设置已经完成,然后发送base64响应正文。

    【讨论】:

    • 这对我仍然不起作用。我启用了直通,我正在发送缓冲区,但它仍然被损坏
    猜你喜欢
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多