1

I am trying to convert the HTML file to pdf and upload it in S3 using Python 3.8 and lambda. I have created a deployment package using pdfkit but while converting to pdf, getting error "[Errno 2] No such file or directory: 'which'". The same piece of code works on my local machine with the local path.

I also tried to create a txt file in /tmp to make sure I have access and it was successfully able to create a file and from there upload to S3. Please help me here.

    s3_upload = boto3.resource('s3')
    bucket_name = 'bucket-invoice'
    html_body = '<html>Hello from test-resource</html>'
    writeFileName = 'test_invoice.pdf'
    local_file_path = '/tmp/local_pdf_file.pdf'

    print('Step 1: ' + local_file_path, html_body)
    pdfkit.from_string(html_body, local_file_path)  # <-- Getting error here

    # Write to S3:
    print('Step 2: Uploading in S3')
    s3_upload.meta.client.upload_file(local_file_path, bucket_name, writeFileName)

    print('Step 3: upload done')

Error Message:

Response:
{
  "errorMessage": "[Errno 2] No such file or directory: 'which'",
  "errorType": "FileNotFoundError",
  "stackTrace": [
    "  File \"/var/task/invoice_api.py\", line 49, in lambda_handler\n    generate_pdf_2()\n",
    "  File \"/var/task/invoice_api.py\", line 161, in generate_pdf_2\n    pdfkit.from_string(html_body, local_file_path)\n",
    "  File \"/var/task/pdfkit/api.py\", line 69, in from_string\n    r = PDFKit(input, 'string', options=options, toc=toc, cover=cover, css=css,\n",
    "  File \"/var/task/pdfkit/pdfkit.py\", line 42, in __init__\n    self.configuration = (Configuration() if configuration is None\n",
    "  File \"/var/task/pdfkit/configuration.py\", line 17, in __init__\n    self.wkhtmltopdf = subprocess.Popen(\n",
    "  File \"/var/lang/lib/python3.8/subprocess.py\", line 854, in __init__\n    self._execute_child(args, executable, preexec_fn, close_fds,\n",
    "  File \"/var/lang/lib/python3.8/subprocess.py\", line 1702, in _execute_child\n    raise child_exception_type(errno_num, err_msg, err_filename)\n"
  ]
}
Mark B
  • 183,023
  • 24
  • 297
  • 295
user1222006
  • 159
  • 1
  • 3
  • 11
  • Have you seen [this](https://stackoverflow.com/questions/52111056/filenotfounderror-errno-2-no-such-file-or-directory-which-when-using-pytho)? – Marcin Mar 23 '20 at 00:58
  • Thanks for the information but I am not sure how I can do this in AWS Lambda. Can you guide me? – user1222006 Mar 23 '20 at 03:00
  • From that issue, the solution was to install and use `wkhtmltopdf` https://wkhtmltopdf.org/. Obviously on lambda you can't install any software, by maybe you can bundle it with your lambda deployment package, or download into `/tmp` for tests. – Marcin Mar 23 '20 at 03:05
  • thanks @Marcin, moved one step further by moving it to `/tmp` and provided full access `` but still getting os.chmod(newfile, 777) denied error. `[ERROR] PermissionError: [Errno 13] Permission denied: '/tmp/bin/wkhtmltopdf'` – user1222006 Mar 23 '20 at 14:42
  • Hi were you able to resolve this? I'm having similar issue – Sharvil Popli Aug 27 '20 at 03:37
  • @SharvilPopli see my answer below – Paolo Dec 24 '21 at 13:15

1 Answers1

0

The issue is that unless it is preconfigured pdfkit is trying to call the "which" command to figure out where the wkhtmltopdf binary is. But "which" is not available on the container running Lambda. If you look at the pdfkit code you can call the configuration object with the contents of the binary.

So for this to work, you could try the following:

config = pdfkit.configuration(wkhtmltopdf=bytes('/opt/bin/wkhtmltopdf','utf-8'))
pdf = pdfkit.from_string(html_body, local_file_path, configuration=config)
b0tting
  • 577
  • 2
  • 7