0

I have referred to many useful links below: Not able to use wkhtmltopdf in containerized AWS lambda How I can use python pdfkit and wkhtmltopdf in aws lambda?

But I keep on getting an os error after successfully running docker.

Below is the lambda code:

import json
import os
import sys
import subprocess

from jinja2 import Environment, FileSystemLoader
# from flask import Flask
import pdfkit

def lambda_handler(event, context):
    #print("==============>>",os.getcwd(), os.path.exists('wkhtml_file/wkhtmltopdf'))

    env = Environment(loader=FileSystemLoader("templates/"))
    content = env.get_template("esign_pdf_old.html")
    # # data_main = json.dumps(json_file)
    content_main = content.render(pdf_data=event)

    # # # Set up the options for PDFKit
    path_to_wkhtmltopdf = "/usr/local/bin/wkhtmltopdf"
    config = pdfkit.configuration(wkhtmltopdf=path_to_wkhtmltopdf)
    options={
            'enable-local-file-access': '',
            'margin-top': '0.2in',
            'margin-right': '0.2in',
            'margin-bottom': '0.4in',
            'margin-left': '0.2in',
            'orientation': 'Landscape',
            'page-size': 'A4',
            'encoding': 'UTF-8',
            'footer-line': '',
            'footer-spacing': 1,
            'footer-font-name': 'Times,serif',
            'footer-font-size': '10'
            }

    # Convert HTML file to PDF
    #output_path = f"/pdf_files/{event.get("message").get('user_details').get('customer_id')}"
    os.makedirs("output",exist_ok=True)
    pdfkit.from_string(content_main, output_path="output",configuration=config, 
    options=options)

    return {
        'statusCode': 200,
        'body': ['Coming from lambda main 2',"wkhtmltopdf is installed"]
    }

below is the Docker file

FROM umihico/aws-lambda-selenium-python:latest
RUN pip install pdfkit==1.0.0 --target ${LAMBDA_TASK_ROOT}
RUN pip install jinja2==3.1.2
RUN yum install -y openssl xorg-x11-fonts-75dpi xorg-x11-fonts-Type1
RUN curl "https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox- 
0.12.6-1.amazonlinux2.x86_64.rpm" -L -o wkhtmltox-0.12.6-1.amazonlinux2.x86_64.rpm
RUN rpm -i wkhtmltox-0.12.6-1.amazonlinux2.x86_64.rpm
# ADD wkhtml_file wkhtml_file
ADD templates templates
COPY lambda_function.py ./
CMD [ "lambda_function.lambda_handler" ]

Below is the error im getting while hitting the api:

http://localhost:9000/2015-03-31/functions/function/invocations

{"errorMessage": "wkhtmltopdf exited with non-zero code 1. error:\nQPainter::begin(): Returned 
false\nExit with code 1, due to unknown error.\n", "errorType": "OSError", "requestId": 
"94020d9f-22ae-4565-afd0-b97fec9d90be", "stackTrace": ["  File 
\"/var/task/lambda_function.py\", line 39, in lambda_handler\n    
pdfkit.from_string(content_main, output_path=\"output\",configuration=config, 
options=options)\n", "  File \"/var/task/pdfkit/api.py\", line 75, in from_string\n    return 
r.to_pdf(output_path)\n", "  File \"/var/task/pdfkit/pdfkit.py\", line 201, in to_pdf\n    
self.handle_error(exit_code, stderr)\n", "  File \"/var/task/pdfkit/pdfkit.py\", line 158, in 
handle_error\n    raise IOError(\"wkhtmltopdf exited with non-zero code {0}. error:\\n{1}\".format(exit_code, error_msg))\n"]}

Note: Im using Windows for the docker build. Should I try Linux for this issue?

M Z
  • 4,571
  • 2
  • 13
  • 27
VJ P
  • 45
  • 5

2 Answers2

1

The following code works fine, only thing is i removed is options.

from jinja2 import Environment, FileSystemLoader
# from flask import Flask
import pdfkit
import os
import boto3
from dotenv import load_dotenv

load_dotenv()

def lambda_handler(event, context):

    env = Environment(loader=FileSystemLoader("templates/"))
    content = env.get_template("esign_pdf_old.html")
    # data_main = json.dumps(json_file)
    content_main = content.render(pdf_data=event)

    path_to_wkhtmltopdf = "/usr/local/bin/wkhtmltopdf"
    config = pdfkit.configuration(wkhtmltopdf=path_to_wkhtmltopdf)

    os.makedirs("output",exist_ok=True)

    pdfkit.from_string(content_main, output_path="output/output.pdf", configuration=config)

    ACCESS_KEY = os.getenv('Access_keys')
    SECRET_KEY = os.getenv('Secret_keys')
    filename = os.getenv('Folder_name')

    bucket_name= os.getenv('Bucket_name')
    file_name= 'output/output.pdf'

    s3 = boto3.client(
        "s3",
        aws_access_key_id=ACCESS_KEY,
        aws_secret_access_key=SECRET_KEY
    )

    with open(file_name, 'rb') as x:
        s3.upload_fileobj(x,bucket_name,filename)

    return {
        'statusCode': 200,
        'file_url': f'https://{bucket_name}.s3.ap-south- 
         1.amazonaws.com/{filename}/{file_name.split("/")[-1]}'}
VJ P
  • 45
  • 5
1

Correct wkhtmltopdf and lambda file worked.

DOCKER file

FROM umihico/aws-lambda-selenium-python:latest 

RUN pip install pdfkit==1.0.0 #--target ${LAMBDA_TASK_ROOT}
RUN pip install jinja2==3.1.2
RUN pip install boto3==1.26.121
RUN pip install python-dotenv==1.0.0
RUN yum install -y openssl xorg-x11-fonts-75dpi xorg-x11-fonts-Type1 libxrender1 
fontconfig xvfb
RUN curl "https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6- 
1/wkhtmltox-0.12.6-1.amazonlinux2.x86_64.rpm" -L -o wkhtmltox-0.12.6- 
1.amazonlinux2.x86_64.rpm
RUN rpm -i wkhtmltox-0.12.6-1.amazonlinux2.x86_64.rpm

ADD whtmltopdf_amazon whtmltopdf_amazon  #Another extra package, neglect it.
RUN chmod -R 777 whtmltopdf_amazon   
ADD templates templates
COPY lambda_function.py ./
CMD [ "lambda_function.lambda_handler" ]

lambda file

def lambda_handler(event, context):

    env = Environment(loader=FileSystemLoader("templates/"))
    content = env.get_template("esign_pdf_fix.html")
    content_main = content.render(pdf_data=event)

    path_to_wkhtmltopdf = "whtmltopdf_amazon/bin/wkhtmltopdf" 
    #"/usr/local/bin/wkhtmltopdf"#"/usr/bin/wkhtmltopdf" 
    config = pdfkit.configuration(wkhtmltopdf=path_to_wkhtmltopdf)
    
    options = {
        'margin-top': '0in',
        'margin-right': '0in',
        'margin-bottom': '0in',
        'margin-left': '0in',
        'enable-local-file-access': None,
        'page-size': 'A4',
        'disable-smart-shrinking': None
    }

    file_name= '/tmp/output.pdf'

    pdfkit.from_string(content_main, output_path=file_name, 
    configuration=config, options=options)
 
    with open(file_name, 'rb') as x:
        #s3.upload_fileobj(x,bucket_name,filename)
        blob_pdf_data = base64.b64encode(x.read())

    return {"blob_data":blob_pdf_data}
VJ P
  • 45
  • 5