What I’m trying to do:
I’m using a FileLoader component to upload an image.
This image then needs to be passed to a Custom HTML form which has JCrop selection implemented such that the user can crop the image.
The problem is that the FileLoader component provides an Anvil Media object which I cannot pass into my custom HTML form.
I need a way of extracting a URL from the media object which is available to the front-end - and pass this URL to the HTML form.
Make a table with three columns: Name (Text), Image (Media Object), and AddedAt (Datetime).
In a server module:
MAX_IMAGES_STORED = 1
@anvil.server.callable()
def get_file_url(file):
print(f"file.content_type: {file.content_type}")
if file.content_type != "image/png" and file.content_type != "image/jpg" and file.content_type != "image/jpeg":
raise Exception(f"file type not allowed")
all_rows = app_tables.input_images.search(tables.order_by('AddedAt'))
if len(all_rows) > MAX_IMAGES_STORED:
rows_to_delete = all_rows[:MAX_IMAGES_STORED]
for row in rows_to_delete:
row.delete()
row = app_tables.input_images.add_row(Image=file, Name=file.name, AddedAt=datetime.now())
return row
This code first checks file type (which you may or may not need to do in your case) - then adds the image to the table, making sure to not upload too many images (hence deleting old images)
Adding the file to the table forces it to have a URL - so when returning the row you can access the url in the front-end (client code) as follows:
If your app is private and you don’t need to be extra secure - you can also make the table accessible by the client which will make this much faster. But in my case its a multi-user application and I don’t want the tables accessible in the client-side.
Your method is generally the one suggested to obtain a URL for a media object that is loaded or generated on the client.
If however you know how your JCrop javascript works, you may be able to interface with it directly using the anvil.js module.
Info Here:
Calling revoke is generally seen as good practice when you no longer need the url of a BlobMedia/FileMedia object.
And is related to the memory management notes here:
Browsers will release object URLs automatically when the document is unloaded; however, for optimal performance and memory usage, if there are safe times when you can explicitly unload them, you should do so.
Either @stucork is just that fast, or it seems to already work with the context manager according to the docstring that popped up when it autocompleted just now:
@stucork can we pass this temporary url to the server? If so, how? I am trying to pass an image url to chatgpt on server to execute a prompt. I cannot seem to get it to work.
Just a guess here, but the temporary url is an object, not a string. If you’re trying to pass the object itself, that probably won’t work. The network protocol understands only some basic data types, not arbitrary object types. See Valid arguments and return values.
The good news is that you can extract the url string from the object, so you could pass that instead. Follow Stu’s documentation link, above, for TempUrl, and read to the bottom. You’ll see how to extract the url string from the object.