Combining an existing PDF into a new ReportLab PDF file through data streams

I have a reportlab SimpleDocTemplate and return it as a dynamic PDF. I create it based on some metadata of the Django model. Here is my template setting:

 buff = StringIO() doc = SimpleDocTemplate(buff, pagesize=letter, rightMargin=72,leftMargin=72, topMargin=72,bottomMargin=18) Story = [] 

I can easily add text metadata from the Entry model to the Story list, which will be built later:

  ptext = '<font size=20>%s</font>' % entry.title.title() paragraph = Paragraph(ptext, custom_styles["Custom"]) Story.append(paragraph) 

And then generate a PDF that will be returned in response by calling build in SimpleDocTemplate :

 doc.build(Story, onFirstPage=entry_page_template, onLaterPages=entry_page_template) pdf = buff.getvalue() resp = HttpResponse(mimetype='application/x-download') resp['Content-Disposition'] = 'attachment;filename=logbook.pdf' resp.write(pdf) return resp 

One metadata field in the model is file attachment. When these file attachments are PDF files, I would like to combine them into the History that I generate; IE stands for fluid reportlab PDF file.

I am trying to do this using pdfrw , but no luck. Ideally, I would just like to call:

 from pdfrw import PdfReader pdf = pPdfReader(entry.document.file.path) Story.append(pdf) 

and add pdf to the existing Story list, which will be included in the final document, as described above.

Does anyone have any idea? I tried something similar, using pagexobj to create a pdf file, trying to follow this example:

http://code.google.com/p/pdfrw/source/browse/trunk/examples/rl1/subset.py

 from pdfrw.buildxobj import pagexobj from pdfrw.toreportlab import makerl pdf = pagexobj(PdfReader(entry.document.file.path)) 

But there was no luck. Can someone explain to me the best way to merge an existing pdf file into reportlab fluid? I'm not very good at it, and the other day I hit my head about pdf format. :) Any direction is much appreciated!

+7
source share
3 answers

I had a similar task in the project. I used reportlab (open source version) to create pdf files and pyPDF to facilitate merging. My requirements were slightly different from the fact that I just needed one page from each application, but I am sure that this is probably close enough so that you can get a general idea.

 from pyPdf import PdfFileReader, PdfFileWriter def create_merged_pdf(user): basepath = settings.MEDIA_ROOT + "/" # following block calls the function that uses reportlab to generate a pdf coversheet_path = basepath + "%s_%s_cover_%s.pdf" %(user.first_name, user.last_name, datetime.now().strftime("%f")) create_cover_sheet(coversheet_path, user, user.performancereview_set.all()) # now user the cover sheet and all of the performance reviews to create a merged pdf merged_path = basepath + "%s_%s_merged_%s.pdf" %(user.first_name, user.last_name, datetime.now().strftime("%f")) # for merged file result output = PdfFileWriter() # for each pdf file to add, open in a PdfFileReader object and add page to output cover_pdf = PdfFileReader(file( coversheet_path, "rb")) output.addPage(cover_pdf.getPage(0)) # iterate through attached files and merge. I only needed the first page, YMMV for review in user.performancereview_set.all(): review_pdf = PdfFileReader(file(review.pdf_file.file.name, "rb")) output.addPage(review_pdf.getPage(0)) # only first page of attachment # write out the merged file outputStream = file(merged_path, "wb") output.write(outputStream) outputStream.close() 
+1
source

I used the following class to solve my problem. It inserts PDF files as vector images in PDF format. It works great because I need to have a table of contents. The fluid object allowed the built-in TOC function to work like a charm.

Is there a matplotlib for ReportLab?

Note. If the file has several pages, you need to slightly modify the class. The sample class is designed to easily read the first page of a PDF.

+1
source

Use this custom method:

 class PDF_Flowable(Flowable): #---------------------------------------------------------------------- def __init__(self,P,page_no): Flowable.__init__(self) self.P = P self.page_no = page_no #---------------------------------------------------------------------- def draw(self): """ draw the line """ canv = self.canv pages = self.P page_no = self.page_no canv.translate(x, y) canv.doForm(makerl(canv, pages[page_no])) canv.restoreState() 

and then after opening an existing PDF, i.e.

  pages = PdfReader(BASE_DIR + "/out3.pdf").pages pages = [pagexobj(x) for x in pages] for i in range(0, len(pages)): F = PDF_Flowable(pages,i) elements.append(F) elements.append(PageBreak()) 

use this code to add this custom stream to the [] elements.

0
source

All Articles