I build a ipywidget button. I hope that when the button is clicked, the program do the computing, and get a result string, then user can download the string as a file.
THe codes are like this:
import ipywidgets as widgets
download_button = widgets.ToggleButton()
download_button.on_click(do_some_work)
def do_some_work(content)-> str:
res = compute()
# Here comes the problem: how to let user download the res as a file?
def compute()-> str:
# ... do_some_compute
return res
I have read ipywidgets doc for plenty times, but could not find a solution.
I use an alternative way now (which seriously affected the user experience): create a HTML widget and when download_button is clicked, change the value of HTML widget to an link to data:text/plain;charset=utf-8,{res}
to let user click and download, but is there any way to achieve this with single one click?
Any help will be much appreciate.
Ipywidget is an open-source python library that is used to generate different types of widgets and implement them in a jupyter notebook. It is easy to use and provides a variety of interactive widgets. In this article, we will explore what are the different types of widgets that ipywidget provides.
The following are 30 code examples of ipywidgets.Button () . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module ipywidgets , or try the search function .
We can select different file formats that can be uploaded by allowing them in the ‘accept’ parameter, also in order to allow multiple files to be uploaded, we will set the ‘multiple’ parameter as True. These are some of the basic and most used widgets that can be created using ipywidgets.
Ipywidget allows us to create a progress bar using one of its widgets named Progress. It can be used to show that something is loading or progress of a certain work. widget.IntProgress ( value=1, min=0, max=10, step=1,description='Progress:', bar_style='info',orientation='horizontal')
The most elegant way I've seen is Solution 1 here (slightly modified and presented below):
from ipywidgets import HTML
from IPython.display import display
import base64
res = 'computed results'
#FILE
filename = 'res.txt'
b64 = base64.b64encode(res.encode())
payload = b64.decode()
#BUTTONS
html_buttons = '''<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<a download="{filename}" href="data:text/csv;base64,{payload}" download>
<button class="p-Widget jupyter-widgets jupyter-button widget-button mod-warning">Download File</button>
</a>
</body>
</html>
'''
html_button = html_buttons.format(payload=payload,filename=filename)
display(HTML(html_button))
Late to the game but if anyone else faces this issue and needs dynamic file content, here is an approach for this. The code is inspired by the answer by @Poompil . Also, there might be more elegant way to bypass browser cache but could not make it to work in Jupyter.
import base64
import hashlib
from typing import Callable
import ipywidgets
from IPython.display import HTML, display
class DownloadButton(ipywidgets.Button):
"""Download button with dynamic content
The content is generated using a callback when the button is clicked.
"""
def __init__(self, filename: str, contents: Callable[[], str], **kwargs):
super(DownloadButton, self).__init__(**kwargs)
self.filename = filename
self.contents = contents
self.on_click(self.__on_click)
def __on_click(self, b):
contents: bytes = self.contents().encode('utf-8')
b64 = base64.b64encode(contents)
payload = b64.decode()
digest = hashlib.md5(contents).hexdigest() # bypass browser cache
id = f'dl_{digest}'
display(HTML(f"""
<html>
<body>
<a id="{id}" download="{self.filename}" href="data:text/csv;base64,{payload}" download>
</a>
<script>
(function download() {{
document.getElementById('{id}').click();
}})()
</script>
</body>
</html>
"""))
Now we can simply add
DownloadButton(filename='foo.txt', contents=lambda: f'hello {time.time()}', description='download')
which adds a download button and the contents of the downloaded file is generated when the button is clocked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With