AWS Lambda 无法 return PDF 文件

AWS Lambda fails to return PDF file

我已经使用 serverless. This function is fired via API Gateway on a GET request and should return a pdf file from a buffer. I'm using html-pdf 创建了一个 lambda 函数来创建缓冲区并尝试使用以下命令return pdf 文件

  let response = {
    statusCode: 200,
    headers: {'Content-type' : 'application/pdf'},
    body: buffer.toString('base64'),
    isBase64Encoded : true,
  };
  return callback(null, response);

但是浏览器无法加载 pdf,所以我不知道如何 return 将 pdf 文件直接加载到浏览器。找不到解决方案。

如果您有一个巨大的 PDF,那么 Lambda 将花费很长时间 return 它并且在 Lambda 中,您按 100 毫秒计费。

我会先保存到S3,然后让Lambda return S3 url 到客户端下载。

嗯,我找到了答案。 我的响应对象中的设置很好,我只需要手动更改 API 网关中的 settings 即可在浏览器中使用。我在 API 网关控制台

的二进制设置下为二进制媒体类型添加了“*/*”

API 网关

  1. 只需登录您的控制台
  2. 选择你的api
  3. 在下拉列表中单击二进制支持
  4. 编辑二进制媒体类型并添加“*/*”

前端

正在新标签页中打开 api url (target="_blank")。浏览器可能正在处理编码的 base 64 响应,在我使用 chrome 的情况下,浏览器就像我想要的那样在新选项卡中打开 pdf。

在这上面花了几个小时后我发现如果你将 Content handling 设置为 Convert to binary (CONVERT_TO_BINARY) 整个响应必须是 base64,否则我会得到一个错误: Unable to base64 decode the body.

因此我的回复现在看起来像:

callback(null, buffer.toString('base64'));

集成响应:

方法响应:

和二进制媒体类型:

以上解决方案仅适用于特定的内容类型。你不能有更多的内容类型。 只需按照以下两步即可解决多内容类型问题。

  1. 单击“使用 Lambda 代理集成”复选框

API 网关 --> API --> 方法 --> 集成请求

  1. 将您的回复创建为

        let response = {
    
          statusCode: 200,
          headers: {
            'Content-type': 'application/pdf',//you can change any content type
            'content-disposition': 'attachment; filename=test.pdf' // key of success
          },
          body: buffer.toString('base64'),
          isBase64Encoded: true
        };
        return response;
    

注意* - 它不安全

我有一个类似的问题,其中 pdf 作为 base64 下载并在更改 serverles.yml 文件时开始发生:

binaryMediaTypes:
      - '*/*'

binaryMediaTypes:
      - 'application/pdf'
      - '....other media types'

问题是因为 AWS 实施此功能的方式。来自 aws 文档 here:

When a request contains multiple media types in its Accept header, API Gateway honors only the first Accept media type. If you can't control the order of the Accept media types and the media type of your binary content isn't the first in the list, add the first Accept media type in the binaryMediaTypes list of your API. API Gateway handles all content types in this list as binary.

基本上,如果接受请求 header 中包含的第一个媒体类型不在您的 binaryMediaTypes 列表中,那么您将返回 base64。

我在浏览器中检查了请求,接受 header 中的第一个媒体类型是 text/html 所以我在更改设置后让它工作至:

binaryMediaTypes:
          - 'application/pdf'
          - '....other media types'
          - 'text/html'

希望这对遇到同样问题的人有所帮助。