File download in Voila from Jupyter Notebook
Asked Answered
N

1

9

There are many questions with great answers about downloading a file from a Jupyter Notebook. Here's one I added to earlier. That works, but I am unable to click and download that file for a server started with Voila.

Originally I realized I could not download the basic case when clicked through Voila.

from IPython.display import display, FileLink

local_file = FileLink('./demo.xlsx', result_html_prefix="Click here to download: ")
display(local_file)

output screenshot

That is from my notebook. I am able to click on the link and download the file. When I start my notebook with Voila it looks more like this.. enter image description here

Clicking the link give a 404 ☝️ for a voila server started with

voila mynotebook.ipynb

Since the file clearly isn't being served... I found this link here and tried:

voila mynotebook.ipynb --VoilaConfiguration.file_whitelist="['demo.xlsx']"

which unfortunately didn't work.

I saw static content can be served in voila.. I'll keep playing down this road. Has anyone done this before?

Nationalist answered 1/2, 2020 at 1:15 Comment(2)
I see, there are lot of troubles going from jupyter to voila.... It looks so promising, but this is a second thing that is a showstopper for me todayGrith
Well, I wouldn't call it a show stopper. By hosting the file as static content and using an anchor tag I could successfully download the file, and style the link however I want for a deployed environment. Not bad, though not clean.Nationalist
N
5

I was able to make it work by hosting my file to download as static content as I was trying before. All of this is for a Mac, but it'll be similar for other platforms.

I had to define a custom template in order to get files at static_root so they could be served. Relevant documentation is here for setting up a custom template.

It isn't difficult.. you essentially create a directory where it's expected, copy over some of the default files, then add/change what you will. terminal record might look something like this:

cd ~/Library/Jupyter/voila/templates/
mkdir foobar
export DEFAULT_TEMPLATE_PATH=~/anaconda3/envs/voilatest/share/jupyter/voila/templates/default
export TEMPLATE_PATH=~/Library/Jupyter/voila/templates/foobar
cp -r $DEFAULT_TEMPLATE_PATH/nbconvert_templates $TEMPLATE_PATH
cp -r $DEFAULT_TEMPLATE_PATH/templates $TEMPLATE_PATH

to which the tree will look like this in my new custom template:

 {~/Library/Jupyter/voila/templates/foobar}$  tree .
.
├── nbconvert_templates
│   ├── base.tpl
│   ├── lab.tpl
│   └── voila.tpl
├── static
│   └── demo.xlsx
└── templates
    ├── 404.html
    ├── browser-open.html
    ├── error.html
    ├── page.html
    └── tree.html

3 directories, 9 files

notice the static directory with demo.xlsx. I added that in. That is the file I wanted to download via the link.

Starting voila like this...

voila mynotebook.ipynb --template=foobar

Now.. in mynotebook.ipynb

Use an HTML Anchor tag to do the download. At least FileLink fails for me with the following error.

Path (/voila/static/demo.xlsx) doesn't exist. It may still be in the process of being generated, or you may have the incorrect path.

which isn't much of a surprise since the actual path the file is stored at isn't that. It just happens to be the static content uri.

%%html
<a href="./voila/static/demo.xlsx" download="demo.xlsx">Download Excel Sheet</a>

Using an anchor will make it hardcoded and I didn't have any issues. I'll also be able to style the anchor more anyways. One catch.. This doesn't work in a regular notebook anymore since it's a URI to a served resource under voila.

Nationalist answered 1/2, 2020 at 3:31 Comment(1)
Putting in static let my code see the file too. Something the question states the answer didn't reiterate is that you need to white-list the file when you run voila. --VoilaConfiguration.file_whitelist="['demo.xlsx']"Nutt

© 2022 - 2024 — McMap. All rights reserved.