Place image in PDF from API call in python?

Question:

Is there any way to place an image to pdf from an url in python? The idea is to generate a pdf with its related image from an API call.
I tried with reportlab and its class ImageReader. After I run this code it crashes the program since io_url is too large.

img = 'url_path'
io_url = urllib.request.urlopen(img).read()
image = ImageReader(io_url)

EDIT — Trying with Flask:

class PostDogQR(Resource):

def get(self, usermail, dog_name ):

  client = pymongo.MongoClient('credentials')
  filter={'UserMail':usermail,'title':dog_name}

  result = client['dbname']['collection'].find(
    filter=filter
  )
  json_response = json.dumps(list(result), default=json_util.default)
  dog = json.loads(json_response)

  df = pd.DataFrame(dog).to_dict()
  title = df['title'][0]
  breed =df['Breed'][0]
  img_url = 'image_url'
  dog_img = df['DogImg'][0]
  dog_age = df['DogAge'][0]
  dog_desc = df['DogDescription'][0]

  pdf = FPDF(unit='mm')
  pdf.set_font('Arial', 'B', 12)
  pdf.add_page()
  pdf.multi_cell(120.0,4.0,f'Hello! My name is {title}.nI am a {breed} and I am {dog_age} years old.nnThis is my story: {dog_desc}',border=0)
  pdf.image(img_url,150,10,50,60)
  #pdf.output("yourfile.pdf", "F")
  response = make_response(pdf.output(dest='S').encode('latin-1'))
  response.headers.set('Content-Disposition', 'attachment', filename= dog_name + '_' + usermail + '.pdf')
  response.headers.set('Content-Type', 'application/pdf')
  return response

I get:

RuntimeError: FPDF error: Missing or incorrect image file: "here it comes my url image address"

Answers:

have you tried using Image from the platypus library?

from reportlab.platypus import Image

try:
    img = Image(img_url)
    img._restrictSize(0.4 * inch, 0.4 * inch)
    img.drawOn(myCanvas, xVal, yVal)
except:
    pass     

A working example (taking c to be the canvas variable):

   img = Image('https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg')
   img._restrictSize(300, 600)
   img.drawOn(c, 0, 0)
Answered By: Conor

Based on the fact that your requirement is to use a dynamic image url…this will work for you:

(Take it that "c" is your canvas variable)

import urllib.request

urllib.request.urlretrieve('https://source.unsplash.com/random/200x200?sig=1',"image_context.png")
imgSize = 200      
c.drawImage("image_context.png", width=imgSize, x=100, y=100, preserveAspectRatio=True)

Flask example:

import urllib.request
import io
from reportlab.lib.units import inch, mm, cm
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

def pdf():

    # Create Bytestream buffer
    buf = io.BytesIO()
    
    # Create a canvas
    c = canvas.Canvas(buf, pagesize=A4, bottomup=0)

    urllib.request.urlretrieve('https://source.unsplash.com/random/200x200?sig=1',"image_context.png")

    imgSize = 200      
    c.drawImage("image_context.png", width=imgSize, x=100, y=100, preserveAspectRatio=True)

    c.showPage() #show the page
    
    #Save the canvas with the data
    c.save()
    buf.seek(0)

    response = make_response(buf)
    response.headers['Content-Disposition'] = "attachment; filename=" + "report" + ".pdf"
    response.headers['Content-Type'] = 'application/pdf'
    return response
Answered By: Conor
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.