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?

CoopDaddio
  • 577
  • 1
  • 5
  • 20
  • 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. – furas Dec 08 '19 at 05:06
  • [documentation](https://pyfpdf.readthedocs.io/en/latest/reference/output/index.html) shows second parameter in `output()` which let you get it as bytes string. – furas Dec 08 '19 at 05:09
  • @furas if I output it as bytes string, where is that stored? In the PDF variable itself? – CoopDaddio Dec 09 '19 at 01:05
  • 1
    I would expect `content = pdf.output(val+".pdf", 'S')` – furas Dec 09 '19 at 01:09
  • This worked perfectly, thankyou. Do you want to put it as the answer so I can upvote / mark as correct? – CoopDaddio Dec 09 '19 at 04:24

2 Answers2

1

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.

furas
  • 134,197
  • 12
  • 106
  • 148
1

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

IX8
  • 21
  • 2