✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

Best way to handle user upload PDF files

Hi , I’m trying to create an app to work on PDF files. I can see base64 can decode csv or txt file. Need help!
Thanks in advance,

What exactly are you asking by “handle user upload PDF files”?

dcc.Upload (see https://dash.plotly.com/dash-core-components/upload) is a way for you to have users upload PDF files. However, if you are wanting to edit/process PDF files in Dash after a user uploads them, you will need to look for 3rd party code (or write your own) that will handle this.

Without further details, the community may not know how to answer your question.

I am trying to prepare a report based on multiple pdf files .
Here is my 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
import PyPDF2
import pandas as pd
from subprocess import call
from dash.exceptions import PreventUpdate

UPLOAD_DIRECTORY = os.getcwd()

if not os.path.exists(UPLOAD_DIRECTORY):

app = dash.Dash()

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”),

    html.Button('Extract data', id='button'),
    children='Click the button to begin extraction.',style={
    'textAlign': 'center'})

style={"max-width": "500px"},


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_count():
return html.Div([
html.H3(‘Number of files uploaded:’),

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)

def run_script_onClick(n_clicks):
# Don’t run unless the button has been pressed…
if not n_clicks:
raise PreventUpdate

script_fn = UPLOAD_DIRECTORY+'/'+'Metadata_Extraction.py'
# The output of a script is always done through a file dump.
# Let's just say this call dumps some data into an `output_file`
#call(["python3", script_path])
#script_fn = 'script.py'
# Load your output file with "some code"
output_content = pd.read_excel('Metadata_Sample_5.xlsx')

# Now return.
return output_content

Output(“file-list”, “children”),
[Input(“upload-data”, “filename”), Input(“upload-data”, “contents”)],
dash.dependencies.Output(‘output-container-button’, ‘children’),
[dash.dependencies.Input(‘button’, ‘n_clicks’)])

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=3006)

dash.exceptions.IncorrectTypeException: The state argument output-container-button.children must be a list or tuple of

Above error I am not able to resolve…please help!

@app.callback(Output(“file-list”, “children”),
[Input(“upload-data”, “filename”), Input(“upload-data”, “contents”)],
dash.dependencies.Output(‘output-container-button’, ‘children’),
[dash.dependencies.Input(‘button’, ‘n_clicks’)])
def update_output(uploaded_filenames, uploaded_file_contents):

should be

    output=[Output('file-list', 'children'),
            Output('output-container-button, 'children)],
    inputs=[Input('upload-data', 'filename'), 
            Input('upload-data', 'contents'),
            Input('button', 'n_clicks')])
def update_output(uploaded_filenames, uploaded_file_contents, button_clicks):

Your function declaration needs to match the # of inputs. Since you have 2 outputs, ensure you return 2 outputs!

See https://dash.plotly.com/basic-callbacks for more examples.

If you only have one output, then it would be (notice lack of [ ]):

output=Output('file-list', 'children'),