为了账号安全,请及时绑定邮箱和手机立即绑定

在AWS Lambda上用Node.js 20+运行Puppeteer和Chromium生成PDF的实战指南

Running Puppeteer/Chromium on AWS Lambda with Node.js 20+ — Working Guide

使用 Node.js 20+ 在 AWS Lambda 上运行 Puppeteer/Chromium 的操作指南

上次我使用Puppeteer生成PDF时,一切运行良好,当时我们使用的是AWS Linux 2和Node.js 18。但是当我们切换到AWS Linux 2023并升级Node.js版本到20.x之后,开始遇到各种问题。我们解决了这些问题后,最终成功生成了PDF,但生成的PDF却损坏了。

经过与团队的讨论,我们决定将Puppeteer迁移到AWS Lambda,这样无论我们在实例中做出何种更改,都不会影响到PDF的生成功能。这也有助于我们降低成本,因为生成相关的PDF报告是管理员日常执行的任务。我们按照以下步骤成功地将Puppeteer迁移至了AWS Lambda。

1 准备 Lambda 代码:

创建一个任意名字的文件夹;在我的情况中,我需要创建一个叫 puppeteer-lambda 的文件夹。之后,通过以下命令初始化 npm 包。

在终端中输入以下命令来初始化 npm 项目,并自动填写 package.json 文件:

npm init --y

注释:--y 参数会自动确认所有默认设置,无需手动输入确认。

请安装以下包并确保安装的是指定的版本,可以使用下面的命令。

    yarn add @sparticuz/chromium@122.0.0 puppeteer-core@22.5.0

安装完包并进行了一些编辑之后,我的“package.json”如下:

{
  "名称": "puppeteer-lambda",
  "版本": "1.0.0",
  "主文件": "index.mjs",
  "脚本": {
    "测试": "echo \"错误:未指定测试\" && exit 1"
  },
  "关键字": [],
  "作者": "",
  "许可证": "ISC",
  "描述": "",
  "依赖": {
    "@sparticuz/chromium": "122.0.0",
    "puppeteer-core": "22.5.0"
  }
}

现在新建一个叫index.mjs的文件,然后把下面这段代码复制进去:

    import chromium from "@sparticuz/chromium";  
    import puppeteer from "puppeteer-core";  

    export const handler = async (event, _context, _callback) => {  
      let browser = null;  
      let result = null;  

      // await chromium.font("/var/task/fonts/NotoColorEmoji.ttf");  
      // 要使用 URL,建议如下代码  
      // await chromium.font(  
      //   "https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf"  
      // );  

      try {  
        // 从事件对象中提取 HTML  
        const html = event.body.html;  
        const args = [...chromium.args, "--disable-gpu-sandbox"];  

        // 创建 puppeteer 浏览器实例  
        browser = await puppeteer.launch({  
          args: args,  
          defaultViewport: chromium.defaultViewport,  
          executablePath: await chromium.executablePath(),  
          headless: chromium.headless,  
          ignoreHTTPSErrors: true,  
          dumpio: true,  
        });  

        // 创建一个新的页面  
        const page = await browser.newPage();  

        // 将 HTML 内容设置为  
        await page.setContent(html, { waitUntil: "domcontentloaded" });  

        // 将媒体类型设置为屏幕  
        await page.emulateMediaType("screen");  

        // 若使用自定义字体  
        await page.evaluateHandle("document.fonts.ready");  

        // 配置生成 PDF  
        const pdf = await page.pdf({  
          // path: "result.pdf",  
          margin: { top: "100px", right: "50px", bottom: "100px", left: "50px" },  
          printBackground: true,  
          format: "A4",  
        });  

        // 将 PDF 转为 base64 格式  
        result = pdf.toString("base64");  
      } catch (error) {  
        console.log("-----handler---", error);  
      } finally {  
        if (browser !== null) {  
          await browser.close();  
        }  
      }  

      return result;  
    };

你的文件夹结构可以像下面这样:

    .  
    └── puppeteer-lambda/  
        ├── fonts/  (仅当你想要上传字体文件时)/  
        │   └── NotoNaskhArabic-VariableFont_wght.ttf   (任何字体文件,如)  
        ├── node_modules  
        ├── index.mjs  
        ├── package.json  
        └── yarn.lock   (取决于你使用的包管理器)

现在打开文件夹并把文件夹里的所有文件压缩:_(注意:nodemodules也会被压缩在一起)

Compressing the files \(Mac\) — Same procedure for Windows

压缩文件(Mac)— 在Windows上操作步骤相同

2号) 在 AWS Lambda 上部署代码

访问https://console.aws.amazon.com/并登录您的账户。在搜索栏中输入Lambda,然后点击搜索结果。接下来,点击创建函数按钮。

在 AWS 控制台里找 Lambda

Searching for Lambda in AWS Console

现在在创建面板中配置您的Lambda函数。我把它命名为puppeteer-lambd;您可以根据喜好为其命名。如果有需要的话,可以开启函数URL。Lambda函数创建的过程如下:

Lambda 创建屏幕 第1部分

Lambda Creation Screen Section 1

Lambda: 屏幕创建部分 2

Lambda Creation Screen Section 2

创建 Lambda 之后,你会看到如下屏幕;点击配置来更新配置。

Lambda创建完成后

After Lambda Creation Screen

现在,你可以相应地更新内存(RAM)、临时存储空间和超时。

Lambda配置界面

Lambda Configuration Pane

你可以通过两种方式上传压缩文件:如果压缩文件小于50MB的话,你可以直接上传。否则,你需要先将文件上传到S3,再复制其URL到输入框里。

上传压缩包

Uploading Compressed File

现在你可以去测试选项卡里测试一下你的代码

测试Lambda函数的功能

Testing the Lambda Function

现在,你可以在“版本”选项卡中点击按钮来发布新版本出来。

发布新版

Publishing a New Version

3) 在后端添加代码:

你现在可以在后端代码中添加,并在路由中调用这个工具函数来获取PDF文件。

    // index.js

    const AWS = require("aws-sdk");

    AWS.config.loadFromPath(`./aws.config.json`);

    exports.generatePdfFile = async ({ html }) => {
      try {
        const lambda = new AWS.Lambda({});

        // 调用 Lambda 函数
        const lambdaResult = await lambda
          .invoke({
            FunctionName: "puppeteer-lambd",
            Payload: JSON.stringify({
              body: {
                html: html,
              },
            }),
          })
          .promise();

        if (lambdaResult.StatusCode === 200) {
          // 响应体中包含的是 base64 编码的 PDF 内容
          const pdfBase64 = JSON.parse(lambdaResult.Payload);

          // 将 base64 字符串解码为缓冲区(二进制数据)
          const pdfBuffer = Buffer.from(pdfBase64, "base64");

          // 将 PDF 缓冲区返回给客户端
          return pdfBuffer;
        } else {
          console.log(lambdaResult.Payload);
          throw new Error("生成 PDF 发生错误");
        }
      } catch (error) {
        console.error("调用 Lambda 函数失败:", error);
        throw new Error("生成 PDF 发生错误");
      }
    };

添加一个用于 AWS 账户信息的配置文件以...

{
  "accessKeyId": "<your-access-key>",  // 访问密钥ID
  "secretAccessKey": "<your-secret-access-key>",  // 密钥访问密钥
  "region": "<your-region>"  // 地区
}

就这样,祝你编程开心!😊

访问代码:

GitHub - faraasat/running-puppeteer-on-aws-lambda: 文章示例代码示例 - 在 AWS Lambda 上运行 Puppeteer/Chromium 的示例 - 使用 Node.js 20+ - 指南…github.com

如果你喜欢我讲的故事,可以关注我一下,在Farasat Ali — Medium可以找到更多有趣的的小贴士。

你可以在 LinkedInGitHub 上找到我哦。

另外,查看我的个人作品集作品集,网址是:

看看 Farasat 如何实现业务的惊人增长 | 轻松获得最佳效果,更令人惊讶的是,你还可以…认识 Farasat Ali,一位专注于尖端编程和网络技术的软件工程师及计算机科学爱好者…www.farasat.me

查看其他相关文章:

使用 Worker Threads 和 Clusters 扩大 Node.js/Express 应用规模 —— 使用 Worker Threads 和 Clusters 扩展 Node.js/Express 应用简易指南Node.js 是一个流行的基于 Google V8 引擎的 JavaScript 运行环境,它以非阻塞特性著称…blog.stackademic.com
使用React Fiber Offscreen减少阻塞时间以优化Next.js中的3D模型渲染每次我们在Web上执行CPU密集型操作时,页面会变得卡顿且一段时间内无法响应。渲染一个…blog.stackademic.com
用Ready Player、Mixamo和Next.js给你的作品集网站添上活力四射的动画 在当今竞争激烈的世界里,作品集网站不仅仅是漂亮的图片和代码片段的堆砌…
如何优化您的Next.js应用:通过卸载计算密集型任务从主线程到Web WorkersJavaScript,作为我们浏览器上运行的语言,本质上运行在单一主线程上,我们可以将CPU密集型任务卸载到Web Workers上……blog.stackademic.com
在 Next.js 13+ App 目录中使用 @Serwist 启用 PWA — 简单教程Progressive Web App 允许在离线时访问已浏览的页面,推送通知并创建桌面图标。学习如何实现它……blog.stackademic.com
[使用 Redux Toolkit 和 Redux State Sync 在 Next.js 13+ 中进行标签页间的状态同步 — 简单指南

当你在 Next.js 中使用 Redux 时,通常需要同步不同标签页的状态。本文分享了一个简单的方法。
更多详情请访问...https://medium.com/syncing-tabs-in-next-js-13-using-redux-toolkit-redux-state-sync-simple-guide-f953329c6beb?source=post_page-----4ab26510e91b--------------------------------]

如何在Next.js服务器组件中使用Blur Hash生成模糊图学习如何从Blur Hash生成模糊图,以确保快速加载……blog.stackademic.com
在 Next.js 中使用 App 目录添加 PWA — 简单指南PWA,即“渐进式 Web 应用程序”。利用现代网络技术,提供更接近原生应用的用户体验,例如快速加载和离线访问……blog.stackademic.com
栈学苑 🎓

感谢您一直读到最后。在您离开前,

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消