Serialize an image, resize, and send back for Server Modules and REST APIs

(moved to Show & Tell)

One of the really cool features of Anvil is that it has a built-in file loader and a way to save binary media objects in datatables. One the occasion that you might need to serialize a binary image for transmission via a server function or REST API, the process is a bit less straightforward. Having worked through this a bit, I wanted to post a quick summary for future reference. This example uploads an image, serializes it for transmission to a server module, decodes it, resizes it to a thumbnail, and sends it back.

Here is the demo:
https://serialize_decode_resize_image.anvil.app
And a clone: clone:

The key client-side code:

def client_image_to_uri(file_bytes):
	# Provide an argument like self.file_loader_1.file.get_bytes()
    #     This will return a JSON serializable string you can use with APIs
	img_uri = "data:image/png;base64," + base64.b64encode(file_bytes)
	return img_uri

They key server-side code

@anvil.server.callable
def create_thumbnail(full_image_base64_string):
  # decode the base64 string to an image
  full_image = Image.open(BytesIO(base64.b64decode(full_image_base64_string)))
  # resize it to a thumbnail
  thumbnail_image = full_image.resize((70,70))
  # create a byte array from the thumbnail  
  thumbnail_byte_array = BytesIO()
  thumbnail_image.save(thumbnail_byte_array, format='PNG')
  thumbnail_byte_array = thumbnail_byte_array.getvalue()
  # encode the byte array to a base64 string  
  thumbnail_base64_string = base64.b64encode(thumbnail_byte_array).decode('utf8')
  return thumbnail_base64_string
1 Like

Just wanted to mention a few things:

  • If you want to transmit binary data between client and server, the best way to do this is to encode it as a BlobMedia object (if it’s not a Media object already, which file_loader_1.file already is) and pass it to the server. Sending a base64-encoded string works, but there is a 16MB limit to the total payload for a server call or response (excluding Media objects).

    So, while base64-encoding might be useful for REST APIs, the easiest way to send binary data around within Anvil is to pass Media objects.

    Check out the reference documentation about Media objects

  • Of course, if you want to resize an image in browser-side code, you can also use the anvil.image module (docs here)