Example: Upload and Download Files with Plotly Dash

This example demonstrates uploading and downloading files to and from a Plotly Dash app. This example simply saves the files to disk and serves them back to user, but if you want to process uploaded files, try adapting the save_file() function in this example.

Python Source Code

import base64
import os
from urllib.parse import quote as urlquote

from flask import Flask, send_from_directory
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

UPLOAD_DIRECTORY = '/project/app_uploaded_files'

if not os.path.exists(UPLOAD_DIRECTORY):

# Normally, Dash creates its own Flask server internally. By creating our own,
# we can create a route for downloading files directly:
server = Flask(__name__)
app = dash.Dash(server=server)

def download(path):
    """Serve a file from the upload directory."""
    return send_from_directory(UPLOAD_DIRECTORY, path, as_attachment=True)

app.layout = html.Div(
        html.H1('File Browser'),
                'Drag and drop or click to select a file to upload.'
                'width': '100%',
                'height': '60px',
                'lineHeight': '60px',
                'borderWidth': '1px',
                'borderStyle': 'dashed',
                'borderRadius': '5px',
                'textAlign': 'center',
                'margin': '10px'
        html.H2('File List'),
    style={'max-width': '500px'}

def save_file(name, content):
    """Decode and store a file uploaded with Plotly Dash."""
    data = content.encode('utf8').split(b';base64,')[1]
    with open(os.path.join(UPLOAD_DIRECTORY, name), 'wb') as fp:

def uploaded_files():
    """List the files in the upload directory."""
    files = []
    for filename in os.listdir(UPLOAD_DIRECTORY):
        path = os.path.join(UPLOAD_DIRECTORY, filename)
        if os.path.isfile(path):
    return files

def file_download_link(filename):
    """Create a Plotly Dash 'A' element that downloads a file from the app."""
    location = '/download/{}'.format(urlquote(filename))
    return html.A(filename, href=location)

    Output('file-list', 'children'),
    [Input('upload-data', 'filename'), Input('upload-data', 'contents')]
def update_output(uploaded_filenames, uploaded_file_contents):
    """Save uploaded files and regenerate the file list."""

    if uploaded_filenames is not None and uploaded_file_contents is not None:
        for name, data in zip(uploaded_filenames, uploaded_file_contents):
            save_file(name, data)

    files = uploaded_files()
    if len(files) == 0:
        return [html.Li('No files yet!')]
        return [html.Li(file_download_link(filename)) for filename in files]

if __name__ == '__main__':
    app.run_server(debug=True, port=8888)


Assuming that you store this file as myapp.py to /project/myappdirectory in your project workspace, the settings you need to deploy this in SherlockML are:

  • Working Directory: /project/myappdirectory
  • Python Module: myapp
  • Python Object: server (the name of the Flask object used by Dash)

You can also follow the instructions in Developing the application to run the app in development mode.


The app provides a widget to upload files, and maintains a list of download links for previously uploaded files:


Only files that fit in memory on the server you run your app on will work, however for most applications this will not be a problem.