Немного поздно, но мне также нужно было внедрить данные в PDF-файл, созданный в отчете, и в итоге придумали следующее. Он хранит данные как поток EmbeddedFile в PDF. Чтобы найти данные позже, он сохраняет ссылку на объектPDF в качестве ключевого слова (это не является «стандартным», спецификация PDF определяет другие способы определения/обозначения потока EmbeddedFile, но он работает). Данные извлекаются с использованием PyPDF2.
# embeds data in the given reportlab.pdfgen.canvas, addressed by key.
# returns a string that must be added to canvas as a keyword
#
def canvas_embed(canvas, key, data):
from reportlab.pdfbase import pdfdoc
# create a stream object to hold the embedded data
s = pdfdoc.PDFStream(
content=data,
filters=[pdfdoc.PDFBase85Encode, pdfdoc.PDFZCompress])
s.dictionary['Type'] = '/EmbeddedFile'
# add it to the pdf
r = canvas._doc.Reference(s)
# return a string representing the object reference.
# we just use the two reference components concatenated with
# the given key name:
return '{}:{:d}:{:d}'.format(key,
*canvas._doc.idToObjectNumberAndVersion[r.name])
# extract the embedded file identified by key from
# the given PyPDF2.pdf.PdfFileReader
#
def reader_extract(pdfreader, key):
from PyPDF2.generic import IndirectObject
# find the key in the pdf's keywords (reportlab canvas
# separates keywords with ', '), and split it to get
# the object reference
for k in pdfreader.documentInfo['/Keywords'].split(', '):
if k.startswith(key + ':'):
refn, refv = [int(x) for x in k.split(':')[1:]]
break
# fetch the stream data
return IndirectObject(refn, refv, pdfreader).getObject().getData()
# a quick test
#
if __name__ == '__main__':
import StringIO
from reportlab.pdfgen import canvas
from PyPDF2.pdf import PdfFileReader
pdfbuf = StringIO.StringIO()
# create pdf with embedded data
c = canvas.Canvas(pdfbuf)
c.drawString(72.0, 72.0, 'embedded file test')
embedkey = canvas_embed(
canvas=c,
key='myembeddeddata',
data='some embedded data.')
c.setKeywords(['SomeOtherKeyword', embedkey])
c.showPage()
c.save()
pdfbuf.seek(0)
# read embedded data from the pdf
r = PdfFileReader(stream=pdfbuf)
data = reader_extract(pdfreader=r, key='myembeddeddata')
print 'Found: {}'.format(data)
«Ключевые слова», безусловно, не место, чтобы поставить это. У вас есть три возможности, которые могут быть правильными поведением в формате PDF: сохраните объект JSON в собственном PDF-объекте внутри файла, сохраните JSON как встроенный файл внутри PDF или каким-то образом переведите его в XMP и включите в файл PDF как Данные XMP. Я ничего не знаю о ReportLab и поддерживаются ли эти методы, но, возможно, это упрощает поиск. –
Я просто не знаю, как писать/читать любые из них с Python без понимания/реализации полного формата PDF. –
Я не думаю, что это необходимо. Если вы создаете отчет из ReportLab, должно быть много библиотек Python, которые остальное делают для вас. Например, найдите «библиотеку Python XMP», и вы уже найдете множество параметров. –