Image from apptables not showing in pdf

Hello guys,

I’m trying to embed a picture into a pdf using fpdf. The image is stored in data tables in a table called assets. When I get the image from my database and use self.image(image_url_here) in fpdf and pass the url of the image media object, I get Unsupported image format or file not found exception. If I get an image from the web and pass the url in self.image(image_url_here), it works fine.

Please find below a snippet of my server code.

import anvil.email
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.secrets
import anvil.server
import anvil.media
import anvil.pdf

from fpdf import FPDF
import random
from io import BytesIO
import datetime


class REPORT(FPDF):

    def __init__(self):
        FPDF.__init__(self)    

    def generate(self):
        
        try:
          self.add_page()
          self.set_text_color(0, 0, 0)
          
          #### Method one, using image from app_tables.
          image = app_tables.assets.get(name="signature_image")['media']
          #print(image.url)
          
          #formatting url to remove extra tokens in url
          url = ""
          for letter in image.url:
            if letter == '?':
              break
              
            url += letter
            
          self.image(url)  #This generates an error message
          #### End of method one ######
            
            
          ##### Method two, using an image url from the web. 
          #Insert any url here that links to a picture, this works            
          self.image("https://i.ibb.co/Br6mLby/england.png")
          
          #### End of method two ########
          
        except Exception as err:
          print("Error in report class:", err)

### End of CYCLE_REPORT class



@anvil.server.callable
def generate_report_test():
  
  
  report = REPORT()
  report.generate()
  
  try:
    pdf_bytes = report.output(dest='S').encode('latin-1')
      
    pdf_report = anvil.BlobMedia("application/pdf", pdf_bytes, name="Appointment Report.pdf")
          
  except Exception as err:
    print("Error in generate report fxn:", err)
  
  return pdf_report
  

And this is the client code that calls the server function

import anvil.media

#Calling server function
pdf = anvil.server.call('generate_report_test')
anvil.media.download(pdf)

Any ideas why the image from my database doesn’t work?
Thanks.

havent ran your code, but if a media url works from external source, but not from the url from the media object, it usually means that you should return a permanent url by creating an endpoint that returns the media object.

@anvil.server.http_endpoint('get_media/:table/:file_name')
def get_media(table, file_name):
 if table == 'table1':
     return app_tables.table1.get(name=file_name)['file']
 if table =='table2':
     return app_tables.table2.get(name=file_name)['file']

then for the URL you feed to the pdf generator, use: https://your-app.anvil.app/_/api/get_media/table1/photo_name

2 Likes

Thanks joinlook. I had to add the image type in the endpoint url for it to work:

https://your-app.anvil.app/_/api/get_media/table1/photo_name.png

For some reason, FPDF needs to know the type of the image.

1 Like

Hi @Agobin ,

this is quite an old post but I seem to have the same problem.

However, an http endpoint with the image type ending doesn’t work for me.

Did you do any additional changes?

best, Mark

Hi @mark.breuss,

I haven’t made any additional changes. Below is a snippet of the implementation of the solution.

#This is where I defined the api endpoint to get the image
#Put this code somewhere in your webservice module
@anvil.server.http_endpoint('/getimage.png')
def get_report_header_image():
  image = app_tables.assets.get(name="my_logo")['media']
    
  return image

Then somewhere in the module that generates the report using fpdf, this is how I place the image in the report. Below is the code snippet for the implementation:

#Place the image in the pdf report
self.image("https://your_apps_url_here.anvil.app/_/api/getimage.png", x=None, y=None, w=60, h=10)

This worked for me. This is not the most optimized solution but it worked for me. If you need to learn more about the fpdf library, check out this documentation: https://pyfpdf.readthedocs.io/en/latest/Tutorial/index.html#header-footer-page-break-and-image. I hope this helps.

1 Like

Hi @Agobin,

thanks for your swift reply!
I thought it would be enough to add the file type to the url in fpdf.
Anyway it works now - thanks!:grinning:

If anyone is interested I found another solution to the problem in the meantime:

#1. Temporarily store the file "locally"
media_object = article['produktfoto']
  with open('/tmp/produktfoto.jpg', 'wb+') as f:
    f.write(media_object.get_bytes())

#2. in fpdf use the file path to the local image
pdf.image("/tmp/produktfoto.jpg",x = 120, y = 28,w=70,h=42)

Cheers, Mark