Download arbitrary data as a file

I want to be able to download (say) the results of a database read as a CSV from a form in the app. I don’t want to rely on google drive.

Can I do this?

Hi David,

Indeed you can! There’s a specific way to do this with data tables, and a general one for any sort of data.

1. Downloading CSV from data tables specifically

Data tables and views have a to_csv() method. It returns a downloadable Media object:

self.link_1.url = app_tables.my_table.to_csv().url

You can use this method on views as well as tables. So, for example, this server function will return a eg to allow download of just the current user’s data (assuming my_table has a user column):

@anvil.server.callable
def get_csv():
  me = anvil.users.get_user()
  if me is not None:
    return app_tables.my_table.client_readable(user=me).to_csv().url

2. Downloading arbitrary data using HTTP APIs

You can use Anvil’s HTTP API support to serve anything you like! Just define an HTTP endpoint that returns the Media object you want to download, then link to it from your app:

@anvil.server.http_endpoint("/export_data.csv", authenticate_users=True)
def serve_csv():
  me = anvil.users.get_user()
  my_data = app_tables.my_table.client_readable(user=me)
  # Could return any Media object here (eg a Google Drive
  # file, or a BlobMedia created from code)
  return my_data.to_csv()

and then on the client:

  self.link_1.url = anvil.server.get_api_origin() + "/export_data.csv"

Note that if you link to an HTTP endpoint from within your app, the http_endpoint handler has all the session information already (eg “which user is logged in?”). If you just fetched that URL with curl or similar, you’d have to provide HTTP Basic authentication (that’s because we specified authenticate_users=True - otherwise you’d just get a blank session where anvil.users.get_user() returns None.)

Hope that helps!

1 Like

I’m not understanding something.

If I do this on the server and link to it, it opens a new tab but waits forever.
Not sure I understand BlobMedia properly…

@anvil.server.http_endpoint("/test.csv")
def download_csv():
  # Tried many different variables here and content types
  d=[
    "first,line,here",
    "second","Line","here"
  ] 
  o=anvil.BlobMedia("text/csv",d)
  return o

You pass a (binary) string into BlobMedia. Here’s an example app that works for me:

https://anvil.works/ide#clone:RARAPIR27A7FB32P=ULUVKI4KREJNRD7QQEJUZDUG

1 Like

Got it, thanks.
Looks like I tried everything except a simple string.

In my defence, it is Monday …

Thanks again.