Save Google Drive file to server (disk)

Well, I worked out how to get my app to read Google Drive files.
Now I want t osave it to the server’s disk (which Anvil documentaiton ALMOST shows me how to do).

f_gdrive = app_files.data_csv
f_name = '/tmp/data.csv'
with anvil.media.TempFile(f_gdrive) as f_name:
    # What do I put here? I tried a write statement to no avail.

I’ve succeeded at writing (& reading) strings to a file in the /tmp folder.

But I can’t write Google Drive files (that I’ve successfully accessed and read programmatically) to the same folder.

What should I do. The documentation doesn’t’ show what line to put after the ‘:’.

(And whenI did this the write worked OK, but the read failed with an error:

# Writing seems to work
fname = '/tmp/data.csv'
f_bytes = f_gdrive.get_bytes()
f_contents = str(io.BytesIO(f_bytes))
with open(fname, 'w+') as f:
  f.write(f_contents)
 # Reading gives error: File b'<_io.BytesIO object at 0x7f6637be8470>' does not exist
  fname = '/tmp/data.csv'
  with open(fname, 'r') as f:
      f_contents = f.read()

Hi Paul,

The filesystem in Server modules is ephemeral – you can store data there for a short while, but it might not be there on your next server call. It’s fine for caching (eg making a copy of a file you already have in Drive or Data Tables), but we don’t recommend storing data there that you want to be persistent.

with anvil.media.TempFile(media) will write the Media object to a temporary file, which is removed as soon as the with block finishes executing. For example, if you’re uploading a file that’s being used with Pandas, you can do the following:

# On the client:
def file_loader_1_change(self, file, **event_args):
  anvil.server.call('process_csv', file)
# On the server:
@anvil.server.callable
def process_csv(csv_media):
  with anvil.media.TempFile(csv_media) as temp_filename:
    df = pd.read_csv(temp_filename)
  # ... and now do what we like with that data frame ...

Does this make sense?


You can, of course, copy that tempfile to somewhere on the server filesystem, so you can load it from there (rather than pulling it from Google) – but you should check each time whether the file exists, because it will periodically disappear as your server environment gets refreshed.

Something like:

import os

def get_data_frame():
  if not os.path.isfile('/tmp/data.csv'):
    with open('/tmp/data.csv', 'w') as f:
      f.write(app_tables.my_file.get_bytes())

  return pd.read_csv('/tmp/data.csv')

Hope that helps!

If you want the file to reliably persist across server calls without going back to Google to re-read it, you could use Data Tables as a temporary store by creating a media object out of the data and storing it in a media column (https://anvil.works/docs/media).

I do this when people create CSVs from other data stores for downloading but don’t necessarily do the download straight away.

I probably have an example of that somewhere if that sounds helpful.