You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python在AWS Lambda中将含图片表格的HTML转为PDF并上传S3

我之前也遇到过类似的问题,在Lambda里折腾FPDF、pdfKit确实容易踩坑——要么依赖的系统库缺失,要么对复杂HTML(比如带表格、图片)的支持不够。给你几个亲测有效的方案,既能搞定HTML转PDF,又能直接上传到S3:

方案1:WeasyPrint + Lambda层(轻量且稳定)

WeasyPrint对HTML/CSS的支持很完善,能很好处理表格和图片,而且体积比Chrome小很多。核心是要把它的依赖打包成Lambda层,解决环境缺失的问题。

步骤:

  1. 制作Lambda层:

    • 用和Lambda同架构的环境(比如Amazon Linux 2 EC2实例,或者本地用Docker模拟amazonlinux:2镜像),安装WeasyPrint及其系统依赖:
      yum install -y gcc python3-devel cairo-devel pango-devel gdk-pixbuf2-devel
      pip3 install weasyprint -t python/lib/python3.9/site-packages/
      
    • 把python目录打包成zip,上传到Lambda作为层。
  2. Lambda函数代码:

    import weasyprint
    import boto3
    from io import BytesIO
    import os
    
    def lambda_handler(event, context):
        # 从event获取HTML内容,或者从S3读取HTML文件
        html_content = event.get("html_content", "")
        
        # 生成PDF到内存缓冲区
        pdf_buffer = BytesIO()
        # 如果HTML里有本地图片,可以转成base64嵌入,或者确保Lambda能访问图片URL
        weasyprint.HTML(string=html_content).write_pdf(pdf_buffer)
        pdf_buffer.seek(0)
        
        # 上传到S3
        s3_client = boto3.client("s3")
        s3_client.put_object(
            Bucket=os.environ["S3_BUCKET_NAME"],
            Key=f"generated_pdfs/{context.aws_request_id}.pdf",
            Body=pdf_buffer,
            ContentType="application/pdf"
        )
        
        return {
            "statusCode": 200,
            "body": f"PDF已上传至S3:s3://{os.environ['S3_BUCKET_NAME']}/generated_pdfs/{context.aws_request_id}.pdf"
        }
    

方案2:Headless Chrome(pyppeteer) + Lambda层(完美还原网页样式)

如果你的HTML有复杂的JS交互或者CSS动画,pyppeteer(Python版Puppeteer)会更合适,它模拟真实Chrome渲染,生成的PDF和网页几乎一致。

步骤:

  1. 添加Chrome Lambda层:
    可以直接使用社区维护的Chrome层(包含Chrome二进制文件和依赖),或者自己打包适配Lambda环境的Chrome资源。

  2. Lambda函数代码:

    import asyncio
    import pyppeteer
    import boto3
    from io import BytesIO
    import os
    
    async def render_html_to_pdf(html_content):
        # 启动无头Chrome
        browser = await pyppeteer.launch(
            headless=True,
            args=["--no-sandbox", "--disable-dev-shm-usage", "--single-process"]
        )
        page = await browser.newPage()
        # 设置页面内容,支持加载外部图片、CSS
        await page.setContent(html_content, waitUntil="networkidle0")
        # 生成PDF,printBackground=True确保背景图/颜色正常显示
        pdf_bytes = await page.pdf(format="A4", printBackground=True)
        await browser.close()
        return pdf_bytes
    
    def lambda_handler(event, context):
        html_content = event.get("html_content", "")
        # 运行异步生成PDF的逻辑
        loop = asyncio.get_event_loop()
        pdf_bytes = loop.run_until_complete(render_html_to_pdf(html_content))
        
        # 上传到S3
        s3_client = boto3.client("s3")
        s3_client.put_object(
            Bucket=os.environ["S3_BUCKET_NAME"],
            Key=f"generated_pdfs/{context.aws_request_id}.pdf",
            Body=BytesIO(pdf_bytes),
            ContentType="application/pdf"
        )
        
        return {
            "statusCode": 200,
            "body": f"PDF已上传至S3:s3://{os.environ['S3_BUCKET_NAME']}/generated_pdfs/{context.aws_request_id}.pdf"
        }
    

关键注意事项

  • 图片资源处理:如果HTML里的图片是本地文件,建议转成base64嵌入HTML;如果是远程URL,要确保Lambda有访问该URL的权限(比如配置VPC互联网访问、添加对应权限)。
  • Lambda配置调整:生成PDF需要一定资源,建议把Lambda内存调到1024MB以上,超时时间设置为30秒(根据PDF大小灵活调整)。
  • 权限设置:给Lambda的IAM角色添加S3上传权限,确保能读写目标S3存储桶。

内容的提问来源于stack exchange,提问作者yasir kk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:47:31