I have modified the dcc.Upload example at Upload | Dash for Python Documentation | Plotly
The original one works fine, but as soon as I insert one more instance of dcc.Upload so I can have second upload box, and setup its individual callback, both dcc.Uploads stop working. They are not even called anymore.
For example, from screenshot below, I have two dcc.Uploads setup.
upload = dcc.Upload(
id=āupload-dataā,
ā¦
ā¦
upload1 = dcc.Upload(
id=āupload-data1ā,
ā¦
ā¦
I have the original callback setup as it is in the example
@app.callback([Output('output-data-upload', 'children'),
Output('file1', 'children')],
[Input('upload-data', 'contents')],
[State('upload-data', 'filename'),
State('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return [children, list_of_names]
#Need to add default return statement in case if condition is not
#executed or true.
return dash.no_update, dash.no_update
But as soon as I setup upload1 callback, both of them stop working. I end up deleting call to update_output1, then the code works for the original dcc.upload.
In short, how can I have two dcc.uploads setup. I am not sure what I am doing wrong in my callbacks. I do not see any errors either in my log. The second callback for the second dcc.uploader is not even called. The entire code is below.
@app.callback([Output('output-data-upload', 'children'),
Output('file2', 'children')],
[Input('upload-data1', 'contents')],
[State('upload-data1', 'filename'),
State('upload-data1', 'last_modified')])
def update_output1(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return [children, list_of_names]
#Need to add default return statement in case if condition is not
#executed or true.
return dash.no_update, dash.no_update
#Need to add default return statement in case if condition is not
#executed or true.
return dash.no_update, dash.no_update
#Updated March 4, 2025
import dash
import pandas as pd
import json
import dash_html_components as html
import plotly.graph_objects as go
import dash_core_components as dcc
import plotly.express as px
from dash.dependencies import Input, Output, State
from datetime import datetime as dt
import dash_table
import base64
import datetime
import io
import dash_bootstrap_components as dbc
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
app.config['suppress_callback_exceptions'] = True
# the styles for the main content position it to the right of the sidebar and
# add some padding.
CONTENT_STYLE = {
"margin-left": "1rem",
"margin-right": "1rem",
"padding": "3rem 1rem",
}
upload = dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
)
upload1 = dcc.Upload(
id='upload-data1',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
)
filesdisplay = html.Div([dbc.Card(
[
html.Div(
[
dbc.Row(
[
dbc.Col([
dbc.Label("File 1 Name", id='file1'),
]),
dbc.Col([
dbc.Label("File 2 Name", id='file2'),
]),
dbc.Col(html.Button('Submit', id='kbutton', n_clicks=0))
]),
]
),
],
body=True,
)
])
content = html.Div([
upload,
upload1,
filesdisplay,
html.Div(id='output-data-upload'),
], style=CONTENT_STYLE)
app.layout= html.Div([dcc.Location(id="url"), content])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
elif 'xml' in filename:
print("xml file selected")
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
if 'xml' in filename:
return html.Div(["xml file"])
else:
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
df.to_dict('records'),
[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
@app.callback([Output('output-data-upload', 'children'),
Output('file1', 'children')],
[Input('upload-data', 'contents')],
[State('upload-data', 'filename'),
State('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return [children, list_of_names]
#Need to add default return statement in case if condition is not
#executed or true.
return dash.no_update, dash.no_update
@app.callback([Output('output-data-upload', 'children'),
Output('file2', 'children')],
[Input('upload-data1', 'contents')],
[State('upload-data1', 'filename'),
State('upload-data1', 'last_modified')])
def update_output1(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return [children, list_of_names]
#Need to add default return statement in case if condition is not
#executed or true.
return dash.no_update, dash.no_update
if __name__ == '__main__':
print("Running app.py from ReadingXML 02252025")
app.run_server()