All binary data (pictures, uploaded files, etc.) is represented in Anvil as “Media objects”.
Media Objects are created by Anvil APIs such as FileLoader components and the Google Drive API. You can also create them directly in Python code from byte strings or source URLs.
Here are a few things you can do with Media objects:
- Display a picture in an Image component by setting its
sourceproperty to a Media object.
- When a user uploads a file into a FileLoader component, the FileLoader’s
fileproperty is a Media object.
- You can send and receive email attachments as Media objects.
- You can open any Media Object by setting the
urlproperty of a Link to a Media object. This opens or downloads the media when the link is clicked.
- You can trigger a Media Object download in the user’s browser by calling
anvil.download(my_media_object)in any client-side code.
- You can store media in a Data Table, with the “Media” column type.
- Canvas components can take a snapshot of what you’ve drawn as a Media object by calling
- Google Drive files are Media objects. You can set the contents of a new Google Drive by passing
a Media object to
create_file(), or you can upload new contents to an existing file by calling
You can do all these things without needing to manually manipulate the binary data.
If you do need to access the underlying data and metadata, you can use the attributes and methods of the
All Media objects are subclasses of
anvil.Media and all have these attributes and methods:
Tells you the MIME type of this media. This is a string with values like
A number that tells you how many bytes long this media is.
A string containing the filename of this Media object (or
None if it is anonymous)
Gives you a URL where this media can be downloaded, if this Media is “permanent” (e.g. if it is stored in Data Tables, or a Google Drive file). If a Media object is not permanent (e.g. it is an anonymous
BlobMedia object), its
url property will be
None. However, you can still download non-permanent Media objects using Link components, or display them with Image components.
Some media’s URLs are accessible from anywhere on the web (e.g.
But some media objects provide a special URL, which is only valid for this browser session using this app. For example, the
url of media from a data table is only valid in the session when it was generated.
A method that returns the content as a string. For binary content such as images, this isn’t very pretty to print out, but it gives you direct access to the raw content of this Media.
This example gets the
anvil.works website and prints the data and metadata made available by its Media object.
my_media = anvil.URLMedia('https://anvil.works') print('url: %s' % my_media.url) print('content_type: %s' % my_media.content_type) print('length: %s bytes' % my_media.length) # This will be `None` since this is a website, not a file print('name: %s' % my_media.name) # Only print the first 15 bytes print('raw bytes: %s ...' % my_media.get_bytes()[:15])
url: https://anvil.works content_type: text/html length: 38653 bytes name: None raw bytes: <!DOCTYPE html> ...
As well as getting Media objects from FileLoaders, Google Drive and other Anvil APIs, you can construct them yourself in code.
URLMedia gets media from a URL. This example gets media for the Anvil logo,
and displays it in an Image component called
my_media = anvil.URLMedia("https://anvil.works/ide/img/banner-100.png") self.image_1.source = my_media
URLMedia only stores a URL; it does not fetch its data unless the
content_type attributes are accessed, or
get_bytes() is called.
Because of browser security restrictions, it is often not possible to directly grab the bytes in client-side code, although you will still be able to display it in an Image component.
If you get an exception like
Failed to load media: https://anvil.works, the endpoint
you are trying to access may not allow requests from client-side code. Try fetching
the bytes from a Server Module or Uplink script instead.
See Browser Restrictions for more info.
BlobMedia gets its media from a string you specify. This example makes a new BlobMedia
containing a string of text, and then uploads it to an app file on Google Drive.
file_contents = "Hello, world" my_media = anvil.BlobMedia(content_type="text/plain", data=file_contents, name="hello.txt") anvil.google.drive.app_files.my_file.set_media(my_media)
Files can be loaded into the browser using the FileLoader component.
To upload them to your server-side code, simply pass the FileLoader’s
file property as an argument to a server function.
download() function allows you to download any Media object as a file in the user’s web browser. This example creates and downloads a file called
text_file = anvil.BlobMedia('text/plain', 'Hello, world', name='hello.txt') download(text_file)
download() is available in Form code only.
Since you can store
Media objects in your Data Tables, you can download files stored in Data Tables.
Retrieve them in the same way as you would a string, integer or other data type. When the
Media object is retrieved,
it will still be a
Media object; its format does not change from when it was originally loaded into the browser.
You can also create a download button with a Link.
Media objects have a
url property containing a URL that the user can access to download the file.
Set this as a Link component’s
url to give the user a clickable link that downloads the file. Media objects must be ‘permanent’ in order to have a URL - this means they must be stored
in a Data Table, Google Drive, or originally retrieved from a URL.
You can read and write to/from the filesystem in Server Modules just as you would in any Python environment. Your filesystem is your own; other users do not have access to it.
def write_a_file(my_string): with open('/tmp/my-file.txt', 'w+') as f: f.write(my_string)
Anvil also has methods to write to files from Media objects.
If you’re using a Python library that wants you to pass it a filename, this can be really useful for
writing some data into a file, then passing the
file_name to the library you’re using.
with anvil.media.TempFile(media_object) as file_name: # Now there is a file in the filesystem containing the contents of media_object. # The file_name variable is a string of its full path.
Read from files to Media objects using this function:
anvil.media.from_file(file_name, [content_type], [name])