1

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?

5
  • if export can work with file-like object then you can use io.BytesIO or io.StringIO to create file in memory, write in this file and later read from this file. Commented Dec 8, 2019 at 5:06
  • documentation shows second parameter in output() which let you get it as bytes string. Commented Dec 8, 2019 at 5:09
  • @furas if I output it as bytes string, where is that stored? In the PDF variable itself? Commented Dec 9, 2019 at 1:05
  • 1
    I would expect content = pdf.output(val+".pdf", 'S') Commented Dec 9, 2019 at 1:09
  • This worked perfectly, thankyou. Do you want to put it as the answer so I can upvote / mark as correct? Commented Dec 9, 2019 at 4:24

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

0

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.