CoopDaddio
CoopDaddio

Reputation: 637

How to use PyFPDF data as a PDF without having to export (output) it as a PDF?

I am using PyFPDF to create custom PDF documents automatically when a user registers using my custom-built Django application. The PDFs contain information about that persons registration. For each person that registers, I do not want to save their pdf as a separate pdf - I want to mail their PDF immediately after I have formatted it.

pdf = FPDF()
pdf.add_page()
pdf.image(file_path, 0, 0, 210)
pdf.set_text_color(1, 164, 206)
pdf.set_font("helvetica", size=26)
pdf.ln(142)
pdf.cell(0, 0, txt=name, ln=4, align="C")

This is what I have currently to format the PDF, where name is a value retrieved from each individual user's registration.

This is what comes immediately after, and what I want to replace:

val = uuid.uuid4().hex
pdf.output(val+".pdf")

Right now, I am exporting each PDF with a unique filename, and then sending it to each user's email.

What I would prefer is to use the pdf variable directly when sending each email, as below:

finalEmail = EmailMessage(
    subject,
    plain_message,
    from_email,
    [email]
)
finalEmail.attach("Registration.pdf", pdf)
finalEmail.send()

However, Django does not accept this as a valid attachment type, as it is a FPDF variable still.

expected bytes-like object, not FPDF

How would I go about this?

Upvotes: 1

Views: 2665

Answers (4)

Martin Thoma
Martin Thoma

Reputation: 136197

fpdf2 is the maintained alternative to the old fpdf.

Install it via

pip install fpdf2

There it works like this:

from io import BytesIO
from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
pdf.set_font("helvetica", "B", 16)
pdf.cell(40, 10, "Hello World!")
byte_string = pdf.output()
stream BytesIO(byte_string)

output still has a dest parameter, but it is deprecated

Upvotes: 0

Costin
Costin

Reputation: 1

I modify answer from IX8 like this:

content = io.BytesIO(bytes(pdf.output(dest = 'S'), encoding='latin1'))
with open("Registration.pdf", "wb") as temp_file:
temp_file.write(content.getvalue())
now you can use Registration.pdf where you want

Upvotes: 0

IX8
IX8

Reputation: 31

Works for me: content = BytesIO(bytes(pdf.output(dest = 'S'), encoding='latin1'))

Upvotes: 2

furas
furas

Reputation: 142631

In documentation you can see parameter S which gives it as bytes string

content = pdf.output(val+".pdf", 'S')

and now you can use content to create attachement in email.

Upvotes: 2

Related Questions