That’s a good question! The info is all in the docs, but we haven’t brought it all together into a tutorial yet. I have added “make a tutorial about file downloads” to our TODO list, but for now here’s a quick summary:
-
Whatever you want to download is probably a Media object. (If it’s not already, construct one from a string with
BlobMedia()
.) -
Any Media object that can be retrieved from the server has a
url
attribute. Just set that URL as theurl
property of aLink
component, and when you click on the link you will download the media. -
To be downloadable from the server, the media object has to be stored somewhere. If you just create a
BlobMedia
from a string, that object’surl
attribute will beNone
, because it only exists in the browser (or during one server call) - there’s nowhere to get it from when you click the link. -
To make data downloadable, you can save it in a Media column of a data table row, or as a file in Google Drive. (Exporting a data table as CSV using the
to_csv()
method also produces a downloadable media object. You can also callto_csv()
on a data table view.) -
Advanced alternative: If you do want to generate data on the fly, rather than saving it somewhere, create an HTTP API endpoint that returns a Media object. Then use the URL for that API endpoint as the
url
property of yourLink
component.
Note: If you hit an HTTP API endpoint from within a browser session - eg by clicking on aLink
component - you can access the session state from the endpoint function. So, eg, if you’re logged into the Users service, the HTTP endpoint function can checkanvil.users.get_user()
to see whether the download should be permitted.
If you want to see this in action, check out the Secure Download Portal example. The files for download are stored in a Media column in a data table. The media from those columns is then used as the url
for a Link
object.
(Extra note: The url
property of a Media object is a session-specific URL - for security, it will stop working after you’ve closed the app. If you want to make a long-lived URL you can access from other contexts, create an HTTP endpoint instead.)
I hope this helps!