How to get media generated from background task to the client side

So it seems like the .get_state() of the running task is really for communicating information about the task and not returning the final value. (You could use it to give you access inside the running task for example to see how much has been completed, or what file in a list of files it was currently processing, etc.)

Rewriting your code a bit yields:

Server code

@anvil.server.background_task
def create_trxn_pdf_background_task_object(form_object):
  return anvil.pdf.render_form( form_object )


@anvil.server.callable
def create_trxn_pdf_background(form_from_client):
  task_obj = anvil.server.launch_background_task('create_trxn_pdf_background_task_object', form_from_client)
  
  return task_obj

Client Code

task = anvil.server.call('create_trxn_pdf_background' form_to_become_pdf )
while not task.is_completed():
        time.sleep(15)        
#below should be a form self.media_object so that the object is stored in browser memory on the client side, otherwise it will be destroyed as soon as the one request for a url is completed (so it should probably be self.media_object to make it available to the entire form)
media_object = task.get_return_value() 
media_object_url = media_object.url

also this will not work with the media_object.url property since you do not want the media object stored in a data_table, the media_object.url property will point to the clients local machine and so is None. You will have to pass the media object directly into a link. like the documentation here:
(essentially you just set the url of the link to the media_object variable instead of a url string)

https://anvil.works/docs/client/components/basic#link

If a Link’s url property is set to a Media object, it will open or download that media in a new tab.

m = anvil.BlobMedia('text/plain', b'Hello, world!', name='hello.txt')
c = Link(text='Open text document', url=m)

Also also also, I would not use a while loop to delay gathering the status of task.is_completed() I strongly suggest you create a download button or link and make it not visible, then use a timer to check the status of .is_completed() , then if it is, set the link property to download and make the link visible.
You can even hide the download button or link once the user clicks on it.

Edit: I suppose you could also create a button that when clicked just calls

anvil.media.download( self.media_object )

And this would just cause it to download into the users browser without a link. :cake:

1 Like