增加向pdf中添加二维码的功能

This commit is contained in:
胡尧
2025-04-15 16:57:32 +08:00
parent 085e6359ce
commit 6ff8395916
2 changed files with 128 additions and 68 deletions

View File

@@ -2,7 +2,16 @@
import time, datetime
import hashlib
from odoo import models
from typing import Optional
import socket
import os
import logging
import qrcode
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from PyPDF2 import PdfFileReader, PdfFileWriter
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
class Common(models.Model):
_name = 'sf.sync.common'
@@ -92,3 +101,120 @@ class PrintingUtils(models.AbstractModel):
# host = "192.168.50.110" # 可以作为参数传入,或者在此配置
# port = 9100 # 可以作为参数传入,或者在此配置
self.send_to_printer(host, port, zpl_code)
def add_qr_code_to_pdf(self, pdf_path:str, content:str, buttom_text:Optional[str]=False):
"""
在PDF文件中添加二维码
:param pdf_path: PDF文件路径
:param content: 二维码内容
:param buttom_text: 二维码下方文字
:return: 是否成功
"""
if not os.path.exists(pdf_path):
logging.warning(f'PDF文件不存在: {pdf_path}')
return False
# 生成二维码
qr = qrcode.QRCode(version=1, box_size=10, border=5)
qr.add_data(str(content))
qr.make(fit=True)
qr_img = qr.make_image(fill_color="black", back_color="white")
# 保存二维码为临时文件
qr_temp_path = '/tmp/qr_temp.png'
qr_img.save(qr_temp_path)
# 创建一个临时PDF文件路径
output_temp_path = '/tmp/output_temp.pdf'
try:
# 使用reportlab创建一个新的PDF
# 注册中文字体
font_paths = [
"/usr/share/fonts/windows/simsun.ttc", # Windows系统宋体
"c:/windows/fonts/simsun.ttc", # Windows系统宋体另一个位置
"/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", # Linux Droid字体
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", # 文泉驿正黑
"/usr/share/fonts/chinese/TrueType/simsun.ttc", # 某些Linux发行版位置
]
font_found = False
for font_path in font_paths:
if os.path.exists(font_path):
try:
pdfmetrics.registerFont(TTFont('SimSun', font_path))
font_found = True
break
except:
continue
# 读取原始PDF
with open(pdf_path, "rb") as original_file:
existing_pdf = PdfFileReader(original_file)
output = PdfFileWriter()
# 处理第一页
page = existing_pdf.getPage(0)
# 获取页面尺寸
page_width = float(page.mediaBox.getWidth())
page_height = float(page.mediaBox.getHeight())
# 创建一个新的PDF页面用于放置二维码
c = canvas.Canvas(output_temp_path, pagesize=(page_width, page_height))
# 设置字体
if font_found:
c.setFont('SimSun', 14) # 增大字体大小到14pt
else:
# 如果没有找到中文字体,使用默认字体
c.setFont('Helvetica', 14)
logging.warning("未找到中文字体,将使用默认字体")
# 在右下角绘制二维码,预留边距
qr_size = 1.5 * inch # 二维码大小为2英寸
margin = 0.1 * inch # 边距为0.4英寸
qr_y = margin + 20 # 将二维码向上移动一点,为文字留出空间
c.drawImage(qr_temp_path, page_width - qr_size - margin, qr_y, width=qr_size, height=qr_size)
if buttom_text:
# 在二维码下方绘制文字
text = buttom_text
text_width = c.stringWidth(text, "SimSun" if font_found else "Helvetica", 14) # 准确计算文字宽度
text_x = page_width - qr_size - margin + (qr_size - text_width) / 2 # 文字居中对齐
text_y = margin + 20 # 文字位置靠近底部
c.drawString(text_x, text_y, text)
c.save()
# 读取带有二维码的临时PDF
with open(output_temp_path, "rb") as qr_file:
qr_pdf = PdfFileReader(qr_file)
qr_page = qr_pdf.getPage(0)
# 合并原始页面和二维码页面
page.mergePage(qr_page)
output.addPage(page)
# 添加剩余的页面
for i in range(1, existing_pdf.getNumPages()):
output.addPage(existing_pdf.getPage(i))
# 保存最终的PDF到一个临时文件
final_temp_path = pdf_path + '.tmp'
with open(final_temp_path, "wb") as output_file:
output.write(output_file)
# 替换原始文件
os.replace(final_temp_path, pdf_path)
return True
finally:
# 清理临时文件
if os.path.exists(qr_temp_path):
os.remove(qr_temp_path)
if os.path.exists(output_temp_path):
os.remove(output_temp_path)