如何从含图片的文件夹结构自动生成PDF文件
从图片文件夹生成带文件名的PDF文件
需求描述
需要从存储图片的文件夹生成PDF文件,图片的目录结构如下:
folder1/ Image1.jpg Image2.jpg ...... folder2/ img1.jpg pict.jpg name1.jpg
要求自动将所有图片导入PDF,并且在每个PDF页面的对应位置保留该图片的文件名。以下是我尝试编写的代码,但无法正常运行:
import os from PIL import Image from PyPDF2 import PdfFileWriter, PdfFileReader from reportlab.pdfgen import canvas from reportlab.lib.pagesizes import letter # 定义图片文件夹路径 path = "path/to/folder" # 创建PDF写入器 output_pdf = PdfFileWriter() # 遍历文件夹中的图片并添加到PDF for filename in os.listdir(path): if filename.endswith(".jpg") or filename.endswith(".jpeg") or filename.endswith(".png"): # 用Pillow打开图片 with Image.open(os.path.join(path, filename)) as img: # 添加空白页 pdf_page = output_pdf.addBlankPage(width=img.width, height=img.height) # 转换图片为RGB模式并添加到页面 img_rgb = img.convert('RGB') pdf_page.mergeRGBImage(img_rgb) # 添加文件名到页面 c = canvas.Canvas(pdf_page) c.setFont("Helvetica", 8) c.drawString(10, 10, filename) c.save() # 保存最终PDF with open("output.pdf", "wb") as out_file: output_pdf.write(out_file)
问题分析
原代码存在几个核心问题:
PyPDF2的PdfFileWriter.addBlankPage()返回的页面对象无法直接与reportlab的canvas.Canvas兼容,两者的PDF操作逻辑不同mergeRGBImage并非PyPDF2页面对象的有效方法,无法实现图片插入- 直接操作空白页并合并内容的逻辑错误,需要先生成包含图片和文本的完整页面,再合并到最终PDF
修正后的代码
import os from PIL import Image from PyPDF2 import PdfMerger from reportlab.pdfgen import canvas from io import BytesIO def image_to_pdf_with_filename(image_path, output_buffer): # 打开图片获取尺寸 with Image.open(image_path) as img: img_width, img_height = img.size # 临时保存为RGB格式图片(适配reportlab的图片插入要求) temp_img = "temp_img.jpg" img.convert('RGB').save(temp_img) # 创建与图片尺寸一致的PDF画布 c = canvas.Canvas(output_buffer, pagesize=(img_width, img_height)) # 插入图片铺满整个页面 c.drawImage(temp_img, 0, 0, width=img_width, height=img_height) # 在页面左下角添加文件名 c.setFont("Helvetica", 10) c.drawString(10, 10, os.path.basename(image_path)) # 保存画布内容到缓冲区 c.save() # 清理临时文件 if os.path.exists(temp_img): os.remove(temp_img) def generate_pdf_from_folder(folder_path, output_pdf_path): merger = PdfMerger() # 定义支持的图片格式 valid_extensions = (".jpg", ".jpeg", ".png") # 按文件名排序,保证PDF内图片顺序稳定 for filename in sorted(os.listdir(folder_path)): if filename.lower().endswith(valid_extensions): img_full_path = os.path.join(folder_path, filename) # 用BytesIO作为临时PDF缓冲区,避免生成中间文件 temp_buffer = BytesIO() image_to_pdf_with_filename(img_full_path, temp_buffer) # 将临时页面合并到最终PDF temp_buffer.seek(0) merger.append(temp_buffer) # 保存最终PDF文件 with open(output_pdf_path, "wb") as out_file: merger.write(out_file) merger.close() # 调用示例 if __name__ == "__main__": target_folder = "path/to/your/image/folder" # 替换为你的图片文件夹路径 output_file = "image_collection.pdf" generate_pdf_from_folder(target_folder, output_file)
代码说明
- 使用
PdfMerger合并多个单页PDF,每个图片对应一个包含文件名的独立页面 - 通过
reportlab直接生成包含图片和文本的页面,解决不同库的对象兼容问题 - 用
BytesIO作为临时缓冲区,无需生成中间PDF文件,提升效率 - 对文件名进行排序,确保PDF中图片的顺序与文件夹内一致
- 添加临时文件清理逻辑,避免残留文件
内容的提问来源于stack exchange,提问作者maxasela
相关产品推荐
相关产品推荐

