我们想在我们创建的PDF文档中存储一些特定于应用程序的元数据(一个JSON对象)。
我们尝试使用画布。setKeyword and PdfFileReader.documentInfo["/Keywords"]
这适用于一个100 KB的文件,但挂起一个1 MB的文件(documentInfo实际上返回,但需要很长时间> 1min)
是否有另一种方法将文件嵌入到reportlab的PDF文档中?是否有另一种方法读取它与PyPDF2?
(这可能是也可能不是一个足够好的答案,但我还没有足够的声誉来评论…)
长延迟的一个可能原因可能是字符串的编码过程。如果您不介意将PDF读入,添加数据并将其写出来,您可以尝试pdfrw。(声明:我是pdfrw的作者。)这样做的代码看起来像这样:
<>之前从pdfrw导入PdfReader, PdfWritertrailer = PdfReader('source.pdf')trailer.Info.Keywords = my_json_stringPdfWriter () .write("dest.pdf",预告片)之前如果因为字符串编码而不够快,实际上可以将数据存储在文件的其他位置的流中(如果需要,甚至可以压缩它)。
有点晚了,但我也需要在reportlab创建的PDF中嵌入数据,最终想出了下面的方法。它将数据存储为PDF中的EmbeddedFile流。为了稍后查找数据,它存储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)