Returning a file is the tricky thing here. The method qrcode.make(...).show()
returns None
and attempts to show the QR code as a GUI window on the server, which doesn’t do anything. You have to make a Media object and return that.
I made an app for a project I work on that generated colourful branded QR codes in SVG format (because editing the colours is easier with an SVG since it’s just text). The server code looks a bit like this:
import anvil.server
import qrcode
import qrcode.image.svg
from io import BytesIO
@anvil.server.callable
@anvil.server.http_endpoint("/qrcode")
def make_qr_code(qr_code_data, **params):
qr_code_obj = qrcode.make(qr_code_data,
image_factory=qrcode.image.svg.SvgPathImage,
error_correction=qrcode.constants.ERROR_CORRECT_Q,
box_size=25, version=2)
data = BytesIO()
qr_code_obj.save(data)
data.seek(0)
svg_text = data.read()
return BlobMedia("image/svg+xml", svg_text, name="qrcode.svg")
In the app itself, we just use an Image component called qrcode_image
and set the source to be the QR code:
media = anvil.server.call('make_qr_code', "Some text here!")
self.qrcode_image.source = media
If you want an image in PNG format, I’d guess you’ll have to alter the image_factory
used, and you’ll likely need to pass the bytes from the BytesIO object into the BlobMedia constructor directly, but I can’t find the documentation for doing so.
(I had this question myself: Can I write to a Media object as a file?)