用pyfpdf插入Base64图片到pdf中[英] Insert Base64 image to pdf using pyfpdf

本文是小编为大家收集整理的关于用pyfpdf插入Base64图片到pdf中的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在使用Python中的PYFPDF生成PDF文件.我有一个base64,我想将其插入PDF文件中,而不必将其保存为我的文件系统中的图像.但是PYFPDF图像函数仅接受文件路径.

fpdf.image(name, x = None, y = None, w = 0, h = 0, type = '', link = '')

有没有办法(hack)直接从内存中插入base64或缓冲图像,而无需事先保存到文件系统中?我什至在github上检查了他们的源代码,但无法解决.

链接:/fpdf

推荐答案

如注释中提到的@pvg所述,base64功能的覆盖load_resource函数可以解决问题.

import base64,io

def load_resource(self, reason, filename):
    if reason == "image":
        if filename.startswith("http://") or filename.startswith("https://"):
            f = BytesIO(urlopen(filename).read())
        elif filename.startswith("data"):
            f = filename.split('base64,')[1]
            f = base64.b64decode(f)
            f = io.BytesIO(f)
        else:
            f = open(filename, "rb")
        return f
    else:
        self.error("Unknown resource loading reason \"%s\"" % reason)

编辑:

这是一个示例代码,将图像插入PDF中.我在代码中评论了一些说明.

from fpdf import FPDF
import os
import io
import base64


class PDF(FPDF):

    def load_resource(self, reason, filename):
        if reason == "image":
            if filename.startswith("http://") or filename.startswith("https://"):
                f = BytesIO(urlopen(filename).read())
            elif filename.startswith("data"):
                f = filename.split('base64,')[1]
                f = base64.b64decode(f)
                f = io.BytesIO(f)
            else:
                f = open(filename, "rb")
            return f
        else:
            self.error("Unknown resource loading reason \"%s\"" % reason)


    def sample_pdf(self,img,path):

        self.image(img,h=70,w=150,x=30,y=100,type="jpg")
        #make sure you use appropriate image format here jpg/png
        pdf.output(path, 'F')

if __name__ == '__main__':
    img = # pass your base64 image
    # you can find sample base64 here : https://pastebin.com/CaZJ7n6s

    pdf = PDF()
    pdf.add_page()
    pdf_path = # give path to where you want to save pdf
    pdf.sample_pdf(img,pdf_path) 

其他推荐答案

我最近一直在面对这个问题,乌奇哈·马达拉(Uchiha Madara)的答案在我的情况下没有起作用,所以我以稍微不同的方式修复了它.当我使用UCHIHA的方法尝试时,如果您提供图像而没有任何修改,则我会遇到相同的fileNotfound错误(没有load_resource函数).由于我真的需要解决方案,而且没有办法,所以我研究了可以在

中找到的模块代码.

c:/users/user/appdata/local/programs/python/python38/lib/site-packages/fpdf/fpdf/fpdf.py

如果您环顾四周,您会注意到图像是通过_Parsepng函数导入的.因此,我们需要对此进行编辑以接受Base64数据字符串.

基本上,您需要做的修复:

在功能中,您需要在顶部添加一个elif来检查"文件名"是否包含指示其base64的字符串,并且需要导入2个新模块.

复制并粘贴此代码下方的第一个IF statement检查URL:

elif "data:image/png;base64" in name:
                f = name.split('base64,')[1]
                f = base64.b64decode(f)
                f = io.BytesIO(f)

这只是查找每个Base64编码图像的典型字符串,如果它在那里并将其解码.

您需要在脚本顶部导入base64和IO模块,因此只需通过

进行操作
import base64, io

现在,只需像正常的情况一样,仅提供您的base64字符串作为文件路径,并且应该使用(使用Python 3.8进行测试).

如果您有任何疑问,请与我联系,希望我能帮助一些人在将来阅读.

本文地址:https://www.itbaoku.cn/post/2090890.html

问题描述

I'm using pyfpdf in python to generate pdf files. I have a Base64 which I want to insert into a pdf file without having to save it as an image in my file system. But the pyfpdf image function only accepts file path.

fpdf.image(name, x = None, y = None, w = 0, h = 0, type = '', link = '')

Is there a way (hack) to directly insert base64 or buffered image from memory, without having to save into the file system beforehand? I even checked their source code on github and couldn't figure.

link : https://github.com/reingart/pyfpdf/tree/master/fpdf

推荐答案

As @pvg mentioned in the comments, overriding load_resource function with your base64 functionality does the trick.

import base64,io

def load_resource(self, reason, filename):
    if reason == "image":
        if filename.startswith("http://") or filename.startswith("https://"):
            f = BytesIO(urlopen(filename).read())
        elif filename.startswith("data"):
            f = filename.split('base64,')[1]
            f = base64.b64decode(f)
            f = io.BytesIO(f)
        else:
            f = open(filename, "rb")
        return f
    else:
        self.error("Unknown resource loading reason \"%s\"" % reason)

EDIT :

This is a sample code to insert images into pdf. I commented some instructions in code.

from fpdf import FPDF
import os
import io
import base64


class PDF(FPDF):

    def load_resource(self, reason, filename):
        if reason == "image":
            if filename.startswith("http://") or filename.startswith("https://"):
                f = BytesIO(urlopen(filename).read())
            elif filename.startswith("data"):
                f = filename.split('base64,')[1]
                f = base64.b64decode(f)
                f = io.BytesIO(f)
            else:
                f = open(filename, "rb")
            return f
        else:
            self.error("Unknown resource loading reason \"%s\"" % reason)


    def sample_pdf(self,img,path):

        self.image(img,h=70,w=150,x=30,y=100,type="jpg")
        #make sure you use appropriate image format here jpg/png
        pdf.output(path, 'F')

if __name__ == '__main__':
    img = # pass your base64 image
    # you can find sample base64 here : https://pastebin.com/CaZJ7n6s

    pdf = PDF()
    pdf.add_page()
    pdf_path = # give path to where you want to save pdf
    pdf.sample_pdf(img,pdf_path) 

其他推荐答案

I've been facing this issue lately and the answer from Uchiha Madara didn't work in my case, so I fixed it in a slightly different way. When I tried it with Uchiha's Method, I the same FileNotFound Error you do if you supply an image without any modification to your code ( without the load_resource function ). Since I really needed a solution and there was no way around, I looked into the module code which can be found in

C:/Users/user/AppData/Local/Programs/Python/Python38/Lib/site-packages/fpdf/fpdf.py

If you look around there for a bit, you notice that the image is imported via the _parsepng function. So, we need to edit this to accept a base64 data string.

Basically, what you need to do to fix it:

In the function, you need to add an elif at the top to check whether the "filename" contains a string indicating it's base64, and you need to import 2 new modules.

Copy & paste this code below the first if-Statement to check for a URL:

elif "data:image/png;base64" in name:
                f = name.split('base64,')[1]
                f = base64.b64decode(f)
                f = io.BytesIO(f)

This just looks for the string which is typical for every base64-encoded image, and if it's there and decodes it.

You need to import the base64 and the io modules at the top of the script, so just do that via

import base64, io

Now just supply your base64 string as the file path like you would do normally, and it should work ( did on my tests with python 3.8 ).

Contact me if you have any questions, I hope I can help some people reading this in the future.