在Python Flask中使用FPDF从API调用插入动态图片到PDF的问题
解决FPDF无法加载远程图片URL生成PDF的问题
问题根源
你使用的旧版fpdf库(非新版fpdf2)的image()方法不支持直接传入远程图片URL,它会默认把传入的字符串当作本地文件路径处理,因此触发了"找不到文件"的错误。另外你的代码里存在一个明显的错误:img_url = 'image_url'是硬编码的无效字符串,应该替换为从数据库获取的dog_img值。
解决方案
需要先将远程图片下载到内存流中,再传递给FPDF处理,具体步骤如下:
- 用
requests库发送请求获取图片字节数据 - 将字节数据包装成类文件对象(
BytesIO) - 调用
pdf.image()时传入这个类文件对象
修正后的完整代码
from io import BytesIO import requests from flask import make_response from flask_restful import Resource import pymongo import json from bson import json_util import pandas as pd from fpdf import FPDF class PostDogQR(Resource): def get(self, usermail, dog_name ): client = pymongo.MongoClient('credentials') filter={'UserMail':usermail,'title':dog_name} result = client['dbname']['collection'].find(filter=filter) json_response = json.dumps(list(result), default=json_util.default) dog = json.loads(json_response) df = pd.DataFrame(dog).to_dict() title = df['title'][0] breed = df['Breed'][0] # 修正:替换硬编码字符串为数据库获取的真实图片URL img_url = df['DogImg'][0] dog_age = df['DogAge'][0] dog_desc = df['DogDescription'][0] pdf = FPDF(unit='mm') pdf.set_font('Arial', 'B', 12) pdf.add_page() pdf.multi_cell(120.0,4.0,f'Hello! My name is {title}.\nI am a {breed} and I am {dog_age} years old.\n\nThis is my story: {dog_desc}',border=0) # 核心修改:下载远程图片到内存流并插入PDF try: img_response = requests.get(img_url) img_response.raise_for_status() # 检查图片请求是否成功 img_stream = BytesIO(img_response.content) pdf.image(img_stream, 150, 10, 50, 60) except Exception as e: # 图片加载失败时的降级处理,可根据需求调整 pdf.text(150, 40, "Image unavailable") response = make_response(pdf.output(dest='S').encode('latin-1')) response.headers.set('Content-Disposition', 'attachment', filename= f"{dog_name}_{usermail}.pdf") response.headers.set('Content-Type', 'application/pdf') return response
关键代码说明
requests.get(img_url):发送GET请求获取远程图片的字节内容BytesIO(img_response.content):将图片字节数据转换成类文件对象,让FPDF可以像读取本地文件一样处理它img_response.raise_for_status():捕获图片请求失败的情况(比如404、500错误),避免程序直接崩溃- 异常处理块:当图片加载失败时,添加占位文本,保证PDF仍能正常生成返回
内容的提问来源于stack exchange,提问作者Lash
相关产品推荐
相关产品推荐

