Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render.download documentation is missing critical details #1186

Closed
jcheng5 opened this issue Mar 4, 2024 · 2 comments · Fixed by #1193
Closed

render.download documentation is missing critical details #1186

jcheng5 opened this issue Mar 4, 2024 · 2 comments · Fixed by #1193

Comments

@jcheng5
Copy link
Collaborator

jcheng5 commented Mar 4, 2024

The render.download docs don't include a description of what the decorated function is supposed to be/do.

Here's the basic facts. There are two different ways the decorated function can provide data to Shiny:

  1. Return a string. This will be assumed to be a filename; Shiny will return this file to the browser, and the downloaded file will have the same filename as the original, with an inferred mime type. This is the most convenient IF the file already exists on disk. But if the function must create a temporary file, then it shouldn't be used; the temporary file will not be deleted by Shiny... use one of the other methods instead.
  2. yield one or more strings or bytestrings (b"..." or io.BytesIO().getvalue()). If strings are yielded, they'll be encoded in UTF-8. (This is better for temp files as after you're done yielding you can delete the temp file, or use a tempfile.TemporaryFile context manager) With this method, it's important that the @render.download decorator have a filename argument, as the decorated function won't help with that.

The decorated function can be sync or async.

One method is not currently supported but would be really nice: the decorated function could opt to take an argument that's a file-like object, provided by Shiny. This makes e.g. matplotlib.pyplot.savefig much easier to call; as it is, you have to savefig into a BytesIO, then get the value out.


Example app:
https://shinylive.io/py/editor/#code=NobwRAdghgtgpmAXGKAHVA6VBPMAaMAYwHsIAXOcpMASxlWICcyACG4gHQi7oeZZhQyqADbEyImgCMs2UeJZQAzi1Fke9JqwgBXetkUqIqLlwBmjYjBZKAFjQgHeWlozhRCZGgDc45y9Z2DtgYcAAeqG5KKs78Dqg6ZHiulAAmcIzJOjSmEADuNGS2LNkYSjTpUlCMABQAlIhcLM0lNBjxiQD6SpLptRyQA8kDAHJDLAAMyQCME1MsAEwTdbkAAm4eXr4YhFAihFzpZqpiZMRSAFb1jRAtLMYYjFAQqVZlcHCpNdMAnABsAA4JkDpitbi0wiwALwsWYTFgAalhAFYWAAqe6YJ4vN7Y1IQGoAFgAzAB2MF3Mw0ADmySgkJhajKOik8jISnqTRa9Iw9iUZBqYWSHTIGAJdWS6Qg5TI2ChABVGDo4BSWm4yDpGLcqdS1m4XhksKcansyFCBgBBFh8s7Up4wAZgo7Wmj84h22DXLnNdWa25s85XMF6tKG155CBiKBfKkiSiwOBQmoDNlYCC6sB1J1wY7hyPEaNe8HNHXQk7iQOc4ssApFNjEDAAIWwFCUAEkAPL1QwsKQ6Mw3O6UmllKC+HU1PtmZJmJiCM0p9OO71DqfvOAAaxqyxXd2wNDgIlSvf7GGpcDI3j2yqrYAAvgBdIA

@phobson
Copy link

phobson commented Mar 5, 2024

Just a note that the playground covers the general uses cases well:
https://shinylive.io/py/examples/#file-download

@jcheng5
Copy link
Collaborator Author

jcheng5 commented Mar 5, 2024

Thanks @phobson, I was curious how so many apps had done this successfully with no docs or examples! 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants