如何为ReportLab生成的PDF添加页脚页码(第X页/共Y页)?已尝试PyPDF
为PDF添加“第X页,共Y页”页脚的两种实现方法
问题背景
已通过ReportLab生成带表格的PDF,文件生成和客户端获取功能正常,但无法添加“第X页,共Y页”样式的页脚,试过PyPDF2和ReportLab基础用法未成功,现有代码如下:
def create_sample_source_report_pdf(task_id): ...... data generation .......... # Create a byte stream to hold the PDF content pdf_byte_stream = io.BytesIO() # Create a PDF document doc = SimpleDocTemplate(pdf_byte_stream, pagesize=landscape(A4)) # Create a table with the data table = Table(data) # Add style to the table style = TableStyle([ ('TEXTCOLOR', (0, 0), (-1, 0), colors.white), # Header text color ('BACKGROUND', (0, 0), (-1, 0), colors.darkgrey), # Header background color ('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), ('BOTTOMPADDING', (0, 0), (-1, 0), 12), ('BACKGROUND', (0, 1), (-1, -1), colors.lightgrey), # Light grey background for every 2nd row ('GRID', (0, 0), (-1, -1), 1, colors.black), ]) table.setStyle(style) # Build the PDF doc.build([table]) # Spacer for title # Move the pointer to the beginning of the byte stream pdf_byte_stream.seek(0) ##################add text with page x of y # Now you can use the modified byte stream to create a BlobMedia blob_media_pdf = BlobMedia("application/pdf", modified_pdf_byte_stream.read(), name="sample_source_list_with_page_numbers.pdf") return blob_media_pdf
方法一:直接用ReportLab生成时添加页码(推荐)
利用ReportLab的SimpleDocTemplate.build()方法支持的回调函数,在生成PDF时直接绘制页脚,无需后续修改PDF文件。
修改后的完整代码
from reportlab.lib.pagesizes import landscape, A4 from reportlab.platypus import SimpleDocTemplate, Table, TableStyle from reportlab.lib import colors import io def create_sample_source_report_pdf(task_id): ...... data generation .......... # 定义页脚绘制函数 def draw_footer(canvas, doc): # 获取当前页码与总页数 current_page = canvas.getPageNumber() total_pages = doc.page footer_text = f"第{current_page}页,共{total_pages}页" # 设置字体样式 canvas.setFont("Helvetica", 10) # 计算居中位置(距离页面底部20px) text_width = canvas.stringWidth(footer_text, "Helvetica", 10) x_pos = (doc.pagesize[0] - text_width) / 2 y_pos = 20 # 绘制页脚文本 canvas.drawString(x_pos, y_pos, footer_text) # Create a byte stream to hold the PDF content pdf_byte_stream = io.BytesIO() # Create a PDF document doc = SimpleDocTemplate(pdf_byte_stream, pagesize=landscape(A4)) # Create a table with the data table = Table(data) # Add style to the table style = TableStyle([ ('TEXTCOLOR', (0, 0), (-1, 0), colors.white), # Header text color ('BACKGROUND', (0, 0), (-1, 0), colors.darkgrey), # Header background color ('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), ('BOTTOMPADDING', (0, 0), (-1, 0), 12), ('BACKGROUND', (0, 1), (-1, -1), colors.lightgrey), # Light grey background for every 2nd row ('GRID', (0, 0), (-1, -1), 1, colors.black), ]) table.setStyle(style) # Build the PDF并传入页脚绘制函数 doc.build([table], onFirstPage=draw_footer, onLaterPages=draw_footer) # Move the pointer to the beginning of the byte stream pdf_byte_stream.seek(0) # Now you can use the modified byte stream to create a BlobMedia blob_media_pdf = BlobMedia("application/pdf", pdf_byte_stream.read(), name="sample_source_list_with_page_numbers.pdf") return blob_media_pdf
关键说明
draw_footer函数通过canvas.getPageNumber()获取当前页码,doc.page获取总页数- 在
doc.build()时传入onFirstPage和onLaterPages参数,实现所有页面统一添加页脚 - 可通过调整
setFont的字体、大小,以及x_pos、y_pos修改页脚的样式和位置
方法二:用PyPDF2给已生成的PDF添加页码
如果需要对已生成的PDF文件补加页码,可使用PyPDF2的读写能力实现:
替换原代码中##################add text with page x of y部分的代码
from PyPDF2 import PdfReader, PdfWriter from PyPDF2.generic import AnnotationBuilder # 读取已生成的PDF内容 reader = PdfReader(pdf_byte_stream) writer = PdfWriter() total_pages = len(reader.pages) for page_idx, page in enumerate(reader.pages, start=1): writer.add_page(page) # 构造页脚文本 footer_text = f"第{page_idx}页,共{total_pages}页" # 获取页面尺寸,计算文本居中位置 page_width = float(page.mediabox[2]) # 近似计算文本宽度(单字符约5.5px,也可结合ReportLab的stringWidth精准计算) text_width = len(footer_text) * 5.5 x_pos = (page_width - text_width) / 2 y_pos = 20 # 创建文本注释并添加到页面 annotation = AnnotationBuilder.free_text( footer_text, rect=(x_pos, y_pos, x_pos + text_width, y_pos + 12), font="Helvetica", font_size=10, color=(0, 0, 0) ) writer.add_annotation(page_number=page_idx-1, annotation=annotation) # 将修改后的PDF写入新字节流 modified_pdf_byte_stream = io.BytesIO() writer.write(modified_pdf_byte_stream) modified_pdf_byte_stream.seek(0)
关键说明
- 遍历每一页,计算总页数与当前页码
- 使用
AnnotationBuilder.free_text创建文本注释,添加到对应页面 - 若需要更精准的文本宽度计算,可引入ReportLab的
stringWidth方法提前计算
内容的提问来源于stack exchange,提问作者KROLN
相关产品推荐
相关产品推荐

