PDFKit无法将图像转换为PDF。

8
我将使用Python中的PDFkit来将HTML页面转换为PDF。在HTML中,正文只有一个图像标签,其src指向完整的URL,如下所示:
<html>
    <body style="margin: 0px;">
        <img style="-webkit-user-select: none; cursor: -webkit-zoom-in;" src="https://blah.blah.com" height="768">
    </body>
</html>

然而,当我像这样将HTML转换为PDF时:
pdfkit.from_file(file, 'labels.pdf', configuration=config)

我看到的是一个带边框的空白页面,而不是图片。
为什么pdfkit不能转换图片?
我在某处读到我们必须提供完整的图片路径,包括域名。但是我提供的图片URL已经很完整了,那么我做错了什么?

我快速测试了一下,得到了带有图像的PDF。看看是否可以在不传递配置pdfkit.from_file(file, 'labels.pdf')的情况下工作。如果可以,那么你的配置可能有问题。也许你正在使用配置而不是选项? - user6077173
6个回答

10

我按照@Manish Gupta的建议将图片编码为Base64数据字符串。在Python中:

import base64

def get_image_file_as_base64_data():
    with open(FILEPATH, 'rb') as image_file:
        return base64.b64encode(image_file.read())

在我的Jinja2模板中(我知道问题并不特定于Jinja2,但这是我正在使用的):

<img src="data:;base64,{{ get_image_file_as_base64_data() }}">

这是在Django后端中更清晰的渲染模板的方法。谢谢! - Nwawel A Iroume
5
要返回一个适用于Html的字符串,您应该使用base64.b64encode(image_file.read())。decode() - SATYAJEET RANJAN
1
在open()函数调用中,只需将'r'更改为'rb' -- 顺便说一句,Josh的回答非常好! - Ryan Loggerythm

4

我在图片的src中使用文件路径而不是文件URL,例如:

<img src="D:/image/path/pircure.png">

它可以正常工作,也许你可以尝试一下。


1
当环境发生变化时,它将会失败。因此,请坚持使用语言的命名规范。 - Kaleem Ullah
2
我找到了更好的方法。我将图片进行了base64编码,并将其传递给HTML。 - Manish Gupta

3
我很喜欢Adrian Lin的方法。虽然,我正在使用Docker中的Django,以下内容对我非常有效: Python:
from django.template import Context, Template
import pdfkit

template_folder = 'media'
context['media_folder'] = os.path.abspath(template_folder)

template_file = os.path.join(template_folder, 'template.html')
with open( template_file, 'r') as f:
    template = Template(f.read())

html_file = template.render(Context(context))

pdfkit.from_string(html, filename)

HTML模板:

<img src="{{media_folder}}/my_pic.png">

2
这些其他答案对我没有用,但我能够从这里和其他来源拼凑出一些答案,并找到了解决方案。
我有一个包含标签的jinja模板:
<img src="data:image/png;base64,{{ img_string }}" width="500px">

然后,我通过运行以下函数将一张图片作为base64编码的字符串传递给模板:

def image_file_path_to_base64_string(filepath: str) -> str:
  '''
  Takes a filepath and converts the image saved there to its base64 encoding,
  then decodes that into a string.
  '''
  with open(filepath, 'rb') as f:
    return base64.b64encode(f.read()).decode()

最终,忽略杂项的Jinja初始化

# generate html with base64 encoded string of image
html_string = jinja_template.render(
    img_string=image_file_path_to_base64_string('path/to/img.png'))

# generate pdf
pdfkit.from_string(html_string, 'html.pdf')


1

我以一种略微相似的方式解决了它,并且它顺利地转换了图像。

在视图中:

pdf_content = pdfkit.from_string(html_string, False)

在模板标签中:

@register.filter
def get_image_file_as_base64_data(CONTRACTOR_LOGO):
    image_bytes = CONTRACTOR_LOGO.read()
    base64_bytes = base64.b64encode(image_bytes)
    base64_string = base64_bytes.decode("ascii")
    return base64_string

在模板文件中

<img style="height: 35px;" alt="Contractor Logo" src="data:image/png;base64, {{ contractor.logo | get_image_file_as_base64_data }}">

注意:这里我正在将图像文件发送到处理图像并返回base64字符串的模板标签。

0

我正在使用 Flask + Jinja2,我找到的最佳解决方案是基于 current_app.config.root_path 将媒体文件夹作为参数传递:

Python 代码示例:

...
rendered_template = render_template(template_path, **data, media_folder=str(Path(current_app.config.root_path)/'static'))
...

在HTML中:

<img src="{{media_folder}}/img/file_name.png">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接