依賴包:pip install reportlab
Odoo 中附件的下載會經過 ir.http 的 def binary_content() 方法獲取附件內容等必要信息,
所以我們需要繼承 ir.http 模型並重寫 binary_content 方法,對 PDF 類型的附件添加水印,
在 [models.py](http://models.py) 中添加繼承的代碼:
import io import base64 import logging from reportlab.pdfbase import pdfmetrics, ttfonts from reportlab.pdfgen import canvas from reportlab.lib.units import cm from PyPDF2 import PdfFileWriter, PdfFileReader from odoo import fields, models _logger = logging.getLogger(__name__) class IrHttp(models.AbstractModel): _inherit = 'ir.http' def binary_content(self, *args, **kwargs): status, headers, content = super(IrHttp, self).binary_content(*args, **kwargs) content_type = dict(headers).get('Content-Type') print ('------------content_type----------',content_type) if content_type == 'application/pdf': content = self.add_watermark(base64.b64decode(content)) content = base64.b64encode(content) return status, headers, content def _get_watermark(self): """ 獲取水印文本:公司名稱+當前日期 :return: """ return f'{self.env.company.name} {fields.Date.context_today(self)}' def _generate_watermark(self): """ 生成水印 :return: """ # 水印文件臨時存儲路徑: filename = f'E:\DEMO\watermark.pdf' #這是windows環境
# 水印文件臨時存儲路徑 # filename = f'/tmp/watermark.pdf' #這是linux環境
watermark = self._get_watermark() # 獲取畫布並修改原點坐標 c = canvas.Canvas(filename) c.translate(1.5 * cm, -3 * cm) try: font_name = 'SimSun' # 從系統路徑中引入中文字體(新宋) pdfmetrics.registerFont(ttfonts.TTFont('SimSun', 'SimSun.ttf')) except Exception as e: # 默認字體,不支持中文 font_name = 'Helvetica' _logger.error(f'Register Font Error: {e}') # 設置字體及大小,旋轉 -20 度並設置顏色和透明度 c.setFont(font_name, 14) c.rotate(20) c.setFillColor('#27334C', 0.15) # 平鋪寫入水印 print('watermark---------------', watermark) for i in range(0, 30, 6): for j in range(0, 35, 5): c.drawString(i * cm, j * cm, watermark) c.save() return filename def add_watermark(self, content): """ 添加水印 :param content: :return: """ watermark = self._generate_watermark() pdf_input = PdfFileReader(io.BytesIO(content), strict=False) watermark = PdfFileReader(open(watermark, "rb"), strict=False) pdf_output = PdfFileWriter() page_count = pdf_input.getNumPages()
# 遍歷要下載的 PDF 將它的每一頁都和水印文件合並起來 for page_number in range(page_count): input_page = pdf_input.getPage(page_number) input_page.mergePage(watermark.getPage(0)) pdf_output.addPage(input_page) stream = io.BytesIO() pdf_output.write(stream) data = stream.getvalue() return data
最后效果

本文來自:https://ruterly.com/2020/12/27/Odoo-Add-Watermark-to-PDF
