【问题标题】:Lambda download and forward PDF (PDF proxy)Lambda 下载和转发 PDF(PDF 代理)
【发布时间】:2021-11-20 07:38:15
【问题描述】:

我想知道这个 lambda 函数我做错了什么。

目标:

发送 http 选项以获取 PDF 并将其从 Lambda 服务转发给消费者。

当前代码:

"use strict";
const http = require("http");

function getPDF(options, event) {
   console.log(options);
  return new Promise((resolve, reject) => {
    let body = "";
    let statusCode = 0;
    let headers = { };
    
    http
      .request(options, (res) => {
        statusCode = res.statusCode;
        const headersFromReq = res.headers || {};

        res.on("data", (chunk) => (body += chunk));

        res.on("end", function () {
          console.log( statusCode, headers, body);
          resolve({ 
            body: Buffer.from(body).toString(),
            statusCode, 
          headers: {
            ...headersFromReq, 
            //'Content-type': 'application/pdf',
            //'content-disposition': 'attachment; filename=test.pdf'
          }
        });
      })
      .on("error", reject)
      .end();
  });
});
}

exports.handler = async (event) => {
  try {
    const response = await getPDF(event.options, event);
    return response;
  } catch (error) {
    console.error(error);
    return {
      statusCode: 500,
      body: JSON.stringify(error),
      headers: {}
    };
  }
};

无论我尝试了什么,它要么超时,要么不会导致实际需要的 Base64 编码 PDF 响应。

用于测试的参数如下所示:

{
  "options": {
    "hostname": "www.africau.edu",
    "port": 80,
    "path": "images/default/sample.pdf",
    "method": "GET",
    "headers": {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36",
      "Accept": "application/pdf",
      "Accept-encoding": "gzip, deflate, br"
    }
  }
}

当前日志 -


Function Logs
START RequestId: 8d6be86c-788d-4f49-8305-8caf377cd32e Version: $LATEST
2021-09-28T09:01:21.507Z    8d6be86c-788d-4f49-8305-8caf377cd32e    INFO    {
  hostname: 'www.africau.edu',
  port: 80,
  path: 'images/default/sample.pdf',
  method: 'GET',
  headers: {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36',
    Accept: 'application/pdf',
    'Accept-encoding': 'gzip, deflate, br'
  }
}
END RequestId: 8d6be86c-788d-4f49-8305-8caf377cd32e
REPORT RequestId: 8d6be86c-788d-4f49-8305-8caf377cd32e  Duration: 11011.54 ms   Billed Duration: 11000 ms   Memory Size: 128 MB Max Memory Used: 54 MB  Init Duration: 152.43 ms    
2021-09-28T09:01:32.494Z 8d6be86c-788d-4f49-8305-8caf377cd32e Task timed out after 11.01 seconds

【问题讨论】:

    标签: javascript amazon-web-services aws-lambda


    【解决方案1】:

    您的方法存在潜在的概念问题 - 执行可能需要时间。在 lambda 中运行时没有的时间。您的 lambda “技术上”最多需要 15 分钟才能完成执行(尽管您必须明确配置它。我认为默认情况下是 10 秒),但是如果您从 AWS API Gateway 触发它,则可以缩短到 30 秒,这不是您可以配置的限制。这是总最大值。此外,您的 lambda 响应不能大于 6MB,并且通常应该是 JSON,因此您必须将文件转换为 Base64,但同样,如果您通过 api 网关提供该文件,即使该限制再次下降...... lambda 以这种方式无法可靠地完成您正在尝试的事情。但是,AWS 实际上会推荐另一种方法。

    1. 您向 API Gateway 发送触发 lambda 的请求
    2. Lambda 查找请求的文件是否已存在于 S3 中
    • 如果不存在:

      • lambda 下载文件并将其放入 S3。请注意,您现在可以设置 S3 存储桶策略,以便文件仅在 S3 中保留一定时间。您可能不想永远保留它,但最好将其缓存一段时间,以防用户尝试重新下载您的 PDF。这样他们就能更快地得到响应
      • 然后 lambda 生成一个预签名的 S3 URL,指向新下载的文件(一个特殊的 URL,您可以从 S3 请求,仅在几分钟内有效)并在响应中返回它
    • 如果已经存在:

      • lambda 只生成预签名的 S3 URL 并在响应中返回它
    1. 您的客户端(我认为是 UI 应用程序)必须对响应中收到的预签名 URL 生成一个连续请求(因此它直接与 S3 对话)。这样,即使您的用户的互联网连接速度很慢并且他们需要 20 分钟来下载文件,您也不会遇到任何超时......如果文件真的很大并且 lambda 无法快速下载它,您仍然会得到一些够了,但这需要更长的讨论时间。在这种情况下,我假设您的文件小于 15MB。

    【讨论】:

    • 感谢您急需的回答。我想我会转向 AWS 生态系统之外的其他解决方案。
    • 这也是一种选择,但即使您放弃了 AWS 解决方案,您仍然不想按照您尝试的方式进行操作。在提供文件之前,您不需要下载文件。您可以在请求和响应之间通过管道传输数据流,以便您的端点真正充当代理,同时下载和上传数据,而不是一次使用超过几个字节的内存,而不是加载整个 10MB在将其传递给消费者之前将文件放入内存
    猜你喜欢
    • 2011-11-15
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多