Python 在ReportLab生成的PDF中包含base64编码图像

Python 在ReportLab生成的PDF中包含base64编码图像,python,django,reportlab,temporary-files,stringio,Python,Django,Reportlab,Temporary Files,Stringio,我正在尝试解码base64编码的图像,并将其转换为使用ReportLab生成的PDF格式。我现在是这样做的(image\u data是base64编码的图像,story已经是ReportLab的故事了): #我在每个元素后面都添加了一些“故事” 图像高度=1.5*英寸#最大图像高度 img_file=tempfile.NamedTemporaryFile(mode='wb',后缀='.png') img_文件.seek(0) img_file.write(image_data.decode('b

我正在尝试解码base64编码的图像,并将其转换为使用ReportLab生成的PDF格式。我现在是这样做的(
image\u data
是base64编码的图像,
story
已经是ReportLab的故事了):

#我在每个元素后面都添加了一些“故事”
图像高度=1.5*英寸#最大图像高度
img_file=tempfile.NamedTemporaryFile(mode='wb',后缀='.png')
img_文件.seek(0)
img_file.write(image_data.decode('base64'))
img_文件.seek(0)
img_size=ImageReader(img_file.name).getSize()
img\u比率=img\u大小[0]/浮动(img\u大小[1])
img=图像(img_file.name,
宽度=img\U比率*img\U高度,
高度=img_高度,
)
story.append(img)
而且它很管用(尽管在我看来仍然很难看)。我想摆脱临时文件(类似文件的对象不应该这样做吗?)

为了摆脱临时文件,我尝试使用
StringIO
模块创建类似文件的对象并传递它而不是文件名:

#我在每个元素后面都添加了一些“故事”
图像高度=1.5*英寸#最大图像高度
img_file=StringIO.StringIO()
img_文件.seek(0)
img_file.write(image_data.decode('base64'))
img_文件.seek(0)
img_size=ImageReader(img_文件).getSize()
img\u比率=img\u大小[0]/浮动(img\u大小[1])
img=图像(img_文件,
宽度=img\U比率*img\U高度,
高度=img_高度,
)
story.append(img)
但这给了我一个带有以下消息的IOError:“无法识别图像文件”


我知道ReportLab使用PIL读取不同于jpg的图像,但有没有办法避免创建命名的临时文件,而只使用类似文件的对象,而不将文件写入磁盘?

我不熟悉ReportLab,但如果您可以直接使用PIL,这将起作用:

...
img = Image.open(img_file)
width, height = img.size
...
您可以在这里查看PIL Image类

您应该通过
PIL.Image.open
包装StringIO(),因此只需
img\u size=ImageReader(PIL.Image.open(img\u文件)).getSize()
。正如Tommaso的回答所暗示的那样,它实际上是一个围绕Image.size的薄包装。此外,实际上不需要自己计算描述大小,reportlab的绑定模式。Image可以为您完成:

img_height = 1.5 * inch  # max image height
img_file = StringIO.StringIO(image_data.decode('base64'))
img_file.seek(0)
img = Image(PIL.Image.open(img_file),
            width=float('inf'),
            height=img_height,
            kind='bound')
)
story.append(img)

此代码在没有PIL的情况下适用于我,因为图像已经是JPEG: raw只是从字典中提取base64字符串。我只是将解码后的“字符串”包装在一个StringIO中

        raw = element['photographs'][0]['jpeg']
        photo = base64.b64decode(raw)
        c.drawImage(ImageReader(StringIO.StringIO(photo)), 0.5*inch, self.y, height = self.PHOTOHEIGHT, preserveAspectRatio = True)

这个解决方案对我有效。我正在使用Flask和Google应用程序引擎

from reportlab.platypus import Image
from reportlab.lib.units import mm
import cStringIO
from base64 import b64decode

story=[]
encoded_image = "...."
decoded_img = b64decode(encoded_image)
img_string = cStringIO.StringIO(decoded_img)
img_string.seek(0)
im = Image(img_string, 180*mm, 100*mm, kind='bound')
story.append(im)
我已从客户端收到图像并保存在数据库中:

from base64 import b64decode
image = request.files['image'].read()
encoded_image = b64encode(image)