ReportLab - 元数据、创建日期和修改日期

ReportLab - Metadata, CreationDate and ModificationDate

当我使用 Reportlab 创建 pdf 时,如何更改元数据字段 CreationDateModificationDate

Take a look mod设置和创建日期的位置:

D['ModDate'] = D["CreationDate"] = \
             Date(ts=document._timeStamp,dateFormatter=self._dateFormatter)
# ...
return PDFDictionary(D).format(document)

基本上,元数据是保存在二进制字符串末尾的字典,字符串的开头是文件内容(document)。

在 Reportlab 内部,您询问的工作流程可以是:

  • 创建canvas
  • 在上面画点东西
  • 从 canvas
  • 得到 document
  • 用人工 mod 创建 PDFDictionary 并创建日期
  • 格式化文档 PDFDictionary
  • 保存到文件

Change metadata of pdf file with pypdf 也尝试了类似的目标。

ReportLab(当前为 3.5)Canvas 提供 public 方法,如 Canvas.setAuthor(),用于设置 /Author/Title 和其他元数据字段(在 docs 第 4.5 节中称为“内部文件注释”)。

但是,没有覆盖 /CreationDate/ModDate 的方法。

如果您只需要更改日期的格式,您可以简单地使用Canvas.setDateFormatter()方法。

上面描述的方法修改了一个PDFInfo对象,在source中可以看出,但是这是private的一部分PDFDocument(如 Canvas._doc.info)。

如果您确实需要覆盖日期,您可以侵入 canvas 的私有部分,或者只搜索结果文件对象的内容以查找 /CreationDate (...)/ModDate (...),替换括号中的值。

这是一个 quick-and-dirty 示例:

import io
import re
from reportlab.pdfgen import canvas

# write a pdf in a file-like object
file_like_obj = io.BytesIO()
p = canvas.Canvas(file_like_obj)
# set some metadata
p.setAuthor('djvg')
# ... add some content here ...
p.save()

# replace the /CreationDate (similar for /ModDate )
pdf_bytes = file_like_obj.getvalue()
pdf_bytes = re.sub(b'/CreationDate (\w*)', b'/CreationDate (D:19700101010203+01)', pdf_bytes)

# write to actual file
with open('test.pdf', 'wb') as pdf:
    pdf.write(pdf_bytes)

上面的例子只是说明了原理。显然,人们可以使用带有环视等的奇特正则表达式。

来自 pdf spec:

Date values used in a PDF shall conform to a standard date format, which closely follows that of the international standard ASN.1 (Abstract Syntax Notation One), defined in ISO/IEC 8824. A date shall be a text string of the form

( D : YYYYMMDDHHmmSSOHH' mm )