2015-05-15 5 views
1

Мы хотим сохранить некоторые метаданные конкретных приложений (объект JSON) в создаваемых нами PDF-документах.Вложение документов в файлы PDF

Мы пытались использовать canvas.setKeyword и PdfFileReader.documentInfo [ «/ ключевые слова»]

Это работает с 100 КБ файла, но висит с 1 Мб файла с (documentInfo на самом деле вернуться, но требует длительного времени> 1min)

Есть ли другой способ вставить файл в документ PDF с помощью reportlab? Есть ли другой способ прочитать его с помощью PyPDF2?

+2

«Ключевые слова», безусловно, не место, чтобы поставить это. У вас есть три возможности, которые могут быть правильными поведением в формате PDF: сохраните объект JSON в собственном PDF-объекте внутри файла, сохраните JSON как встроенный файл внутри PDF или каким-то образом переведите его в XMP и включите в файл PDF как Данные XMP. Я ничего не знаю о ReportLab и поддерживаются ли эти методы, но, возможно, это упрощает поиск. –

+0

Я просто не знаю, как писать/читать любые из них с Python без понимания/реализации полного формата PDF. –

+0

Я не думаю, что это необходимо. Если вы создаете отчет из ReportLab, должно быть много библиотек Python, которые остальное делают для вас. Например, найдите «библиотеку Python XMP», и вы уже найдете множество параметров. –

ответ

0

(Это может или не может быть достаточно хороший ответ, но я до сих пор не имеют репутацию, чтобы иметь возможность комментировать ...)

Одной из возможных причин длительной задержки может быть процесс кодирования для строки. Если вы не возражаете читать PDF-файл, добавляя данные и записывая их обратно, вы можете попробовать pdfrw. (Отказ от ответственности: Я pdfrw автор.) Код, чтобы сделать это будет выглядеть примерно так:

 
    from pdfrw import PdfReader, PdfWriter 
    trailer = PdfReader('source.pdf') 
    trailer.Info.Keywords = my_json_string 
    PdfWriter().write('dest.pdf', trailer) 

Если это не достаточно быстро из-за строки кодирования, вы могли бы на самом деле хранить данные в потоке где-то else в файле (и даже сжать его, если это необходимо).

0

Немного поздно, но мне также нужно было внедрить данные в 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)