简体   繁体   English

使用无服务器和 chrome-aws-lambda 节点包在 AWS Lambda 上找不到 Chrome 二进制文件

[英]Chrome Binary Not Found on AWS Lambda Using Serverless and chrome-aws-lambda Node package

I have created a simple application that accepts a URL and converts it to a PDF.我创建了一个简单的应用程序,它接受一个 URL 并将其转换为 PDF。 It stores the resultant PDF in an S3 bucket and returns the URL of the PDF.它将生成的 PDF 存储在 S3 存储桶中并返回 PDF 的 URL。 It uses Chrome (running headless) to convert the URL to a PDF.它使用 Chrome(无头运行)将 URL 转换为 PDF。 I used the serverless framework, AWS Lambda, and the chrome-aws-lambda npm package.我使用了无服务器框架、AWS Lambda 和 chrome-aws-lambda npm 包。 When I execute this setup locally using serverless it all works great.当我使用无服务器在本地执行此设置时,一切都很好。 I can use postman to make a request with a URL and it returns the URL of the resultant PDF.我可以使用邮递员通过 URL 发出请求,并返回结果 PDF 的 URL。 When I deploy this setup to AWS Lambda, it returns a 502 internal server error response.当我将此设置部署到 AWS Lambda 时,它会返回 502 内部服务器错误响应。 When I look at the AWS logs for my application I see the following:当我查看我的应用程序的 AWS 日志时,我看到以下内容:

{
    "errorType": "Error",
    "errorMessage": "ENOENT: no such file or directory, open '//../bin/chromium.br'",
    "code": "ENOENT",
    "errno": -2,
    "syscall": "open",
    "path": "//../bin/chromium.br",
    "stack": [
        "Error: ENOENT: no such file or directory, open '//../bin/chromium.br'"
    ]
}

Here is the main handler for the application:这是应用程序的主要处理程序:

import AWS from 'aws-sdk'
import middy from 'middy'
import chromium from 'chrome-aws-lambda'
import {
  cors,
  doNotWaitForEmptyEventLoop,
  httpHeaderNormalizer,
  httpErrorHandler
} from 'middy/middlewares'

const handler = async (event) => {
  // Request body is passed in as a JSON encoded string in 'event.body'
  const data = JSON.parse(event.body)

  const executablePath = event.isOffline
    ? './node_modules/puppeteer/.local-chromium/linux-706915/chrome-linux/chrome'
    : await chromium.executablePath

  const browser = await chromium.puppeteer.launch({
    args: chromium.args,
    defaultViewport: chromium.defaultViewport,
    executablePath: executablePath,
    headless: true
  })

  const page = await browser.newPage()

  await page.goto(data.url, {
    waitUntil: ['networkidle0', 'load', 'domcontentloaded']
  })

  const pdfStream = await page.pdf()

  var upload = new AWS.S3.ManagedUpload({
    params: {
      Bucket: 'bucketname',
      Body: pdfStream,
      Key: `${Date.now()}-result.pdf`,
      ACL: 'public-read'
    }
  })

  var promise = upload.promise()

  return promise.then(
    function (data) {
      console.log(data.Location)
      return {
        statusCode: 200,
        body: data.Location
      }
    },
    function (err) {
      console.log('Error', err)
      return {
        statusCode: 500,
        body: err
      }
    }
  )
}

export const generate = middy(handler)
  .use(httpHeaderNormalizer())
  .use(cors())
  .use(doNotWaitForEmptyEventLoop())
  .use(httpErrorHandler())

Here is the serverless framework configuration file:这是无服务器框架配置文件:

service: print-pdf

package:
  individually: true

provider:
  name: aws
  runtime: nodejs12.x
  region: us-east-2
  stage: prod

plugins:
  - serverless-bundle # Package our functions with Webpack
  - serverless-offline

# Create our resources with separate CloudFormation templates
resources:
  # API Gateway Errors
  - ${file(resources/api-gateway-errors.yml)}
  # S3
  - ${file(resources/s3-bucket.yml)}

# 'iamRoleStatements' defines the permission policy for the Lambda function.
# In this case Lambda functions are granted with permissions to access S3.
iamRoleStatements:
  - Effect: Allow
    Action:
      - s3:GetObject
      - s3:PutObject
    Resource: "arn:aws:s3:us-east-2:*:*"

functions:
  give-me-the-pdf:
    handler: handler.generate
    events:
      - http:
          path: pdf
          method: post
          cors: true
          authorizer: aws_iam

Here is the package.json:这是 package.json:

{
  "name": "print-pdf",
  "version": "1.0.0",
  "main": "handler.js",
  "author": "Dean Andreakis <dean@deanware.com>",
  "license": "MIT",
  "private": true,
  "scripts": {
    "test": "serverless-bundle test"
  },
  "dependencies": {
    "chrome-aws-lambda": "^1.20.4",
    "middy": "^0.28.4",
    "puppeteer-core": "^1.20.0"
  },
  "devDependencies": {
    "aws-sdk": "^2.597.0",
    "jest": "^24.9.0",
    "puppeteer": "^2.0.0",
    "serverless": ">=1.48.1",
    "serverless-bundle": "^1.2.5",
    "serverless-dotenv-plugin": "^2.1.1",
    "serverless-offline": "^5.3.3"
  }
}

Why is Chrome not found when deployed to AWS versus running locally?为什么 Chrome 在部署到 AWS 而不是在本地运行时找不到?

You could use serverless-webpack and configure chrome-aws-lamdba as an external.您可以使用serverless-webpack并将chrome-aws-lamdba配置为外部。

There's a similar issue here .有一个类似的问题在这里

Add this to your webpack config:将此添加到您的 webpack 配置中:

externals: ['aws-sdk', 'chrome-aws-lambda']

serverless-bundle only includes the JS code that you use in your handler and strips everything else to minimize your bundle. serverless-bundle只包含您在处理程序中使用的 JS 代码,并删除其他所有内容以最小化您的包。 That means the chrome binaries are excluded.这意味着排除了 chrome 二进制文件。

To include those binaries, add the following to your serverless.yml :要包含这些二进制文件,请将以下内容添加到您的serverless.yml

custom:
  bundle:
    copyFiles:
      - from: 'node_modules/chrome-aws-lambda/bin/*'
        to: './'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 chrome-aws-lambda 生成 PDF - Generating PDF using chrome-aws-lambda 如何将 chrome-aws-lambda 模块与 AWS lambda 函数一起使用? - How to use chrome-aws-lambda module with AWS lambda functions? chrome-aws-lambda + lighthouse 总是导致 NO_SCREENSHOTS - chrome-aws-lambda + lighthouse always results in NO_SCREENSHOTS chrome-aws-lambda Amazon linux 2 出现错误:套接字挂断 - chrome-aws-lambda Amazon linux 2 getting Error: socket hang up chrome-aws-lambda + lighthouse 总是导致错误:连接 ECONNREFUSED 127.0.0.1:9222 - chrome-aws-lambda + lighthouse always results in Error: connect ECONNREFUSED 127.0.0.1:9222 使用 Selenium 的 AWS Lambda Nodejs 12.x:未找到 Chrome 驱动程序 - AWS Lambda Nodejs 12.x using Selenium: Chrome Driver not found 在使用 Node 的 AWS Lambda 中,无法让 Express 与 aws-serverless-express 一起使用 - In AWS Lambda using Node, can't get Express to work with aws-serverless-express 将aws-serverless-express与node js一起使用时,我们可以创建多个aws lambda函数吗? - can we create multiple aws lambda function when using aws-serverless-express with node js 通过FTP从无服务器AWS Lambda发送二进制图像 - Send Binary Image from Serverless AWS Lambda Over FTP 使用AWS Lambda(节点)在AWS DynamoDB中的UpdateItem - UpdateItem in AWS DynamoDB using AWS Lambda (node)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM