Voila: Downloading a file using FileLink fails

Created on 14 Apr 2020  路  3Comments  路  Source: voila-dashboards/voila

Hi there,

I have created a small jupyter notebook which is served by voil脿 on mybinder. The app takes a file as input, using the Fileinput ipywidget, processes it and returns a new file.

In order to download the processed file I used the FileLink from IPython.display as suggested here:
https://github.com/jupyter-widgets/ipywidgets/issues/2471#issuecomment-580965788

The problem is, that when served with voila on mybinder I get the 403-Forbidden error. Is there any way around that?

Thanks,

Best regards, Alex-

Most helpful comment

Hi @MichaMucha ,

thanks for the useful answer ;)

In the mean time I found an alternate way to do it:

from IPython.display import HTML
def create_download_link(filename, title = "Click here to download: "):  
    data = open(filename, "rb").read()
    b64 = base64.b64encode(data)
    payload = b64.decode()
    html = '<a download="{filename}" href="data:text/csv;base64,{payload}" target="_blank">{title}</a>'
    html = html.format(payload=payload,title=title+f' {filename}',filename=filename)
    return HTML(html)

All 3 comments

Hi!

That's a nice widget :)

Voila would prevent file access to protect the contents of your local environment.

You can set up a whitelist of individual files or regex path patterns on launch.
More about the config here: https://github.com/voila-dashboards/voila/blob/master/voila/configuration.py#L36

In your case you could launch your notebook with
voila MyNotebook.ipynb --VoilaConfiguration.file_whitelist="['demo.xlsx']"

Hope this helps

Hi @MichaMucha ,

thanks for the useful answer ;)

In the mean time I found an alternate way to do it:

from IPython.display import HTML
def create_download_link(filename, title = "Click here to download: "):  
    data = open(filename, "rb").read()
    b64 = base64.b64encode(data)
    payload = b64.decode()
    html = '<a download="{filename}" href="data:text/csv;base64,{payload}" target="_blank">{title}</a>'
    html = html.format(payload=payload,title=title+f' {filename}',filename=filename)
    return HTML(html)

@Alexboiboi
Thanks very much! Very useful. Here is a variation of your code but using html ipywidgets. Tested in Voila and works well.

from IPython.display import HTML
import ipywidgets as widgets
import base64


def edit_download_html(htmlWidget, filename, title = "Click here to download: "):

    # Change widget html temperarily to a font-awesome spinner
    htmlWidget.value = "<i class=\"fa fa-spinner fa-spin fa-2x fa-fw\"></i><span class=\"sr-only\">Loading...</span>"

    # Process raw data
    data = open(filename, "rb").read()
    b64 = base64.b64encode(data)
    payload = b64.decode()

    # Create and assign html to widget
    html = '<a download="{filename}" href="data:text/csv;base64,{payload}" target="_blank">{title}</a>'
    htmlWidget.value = html.format(payload = payload, title = title+filename, filename = filename)

htmlWidget = widgets.HTML(value = '')
htmlWidget
filename = r"C:\your\path\filename.whatever"
title = "Click here to download: "
edit_download_html(htmlWidget, filename, title = title)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

paugier picture paugier  路  6Comments

jeiche picture jeiche  路  8Comments

maartenbreddels picture maartenbreddels  路  7Comments

laserman781 picture laserman781  路  3Comments

tylerburleigh picture tylerburleigh  路  6Comments