我想使用Dash Upload组件(请参见Example from Dash Documentation)上传一个csv文件并将其发布到文件服务器。我希望它像这个working Postman csv Post-Request一样简单。 我的回调目前看起来像这样:
@app.callback(
Output(component_id="eventlog-dropdown", component_property="options"),
[Input(component_id="upload-data", component_property="contents"),
Input(component_id="upload-data", component_property="filename")]
)
def upload_eventlog(uploaded_contents, uploaded_filename):
if uploaded_contents is not None:
eventlog_data = [
parse_contents(c, n) for c, n in
zip(uploaded_contents, uploaded_filename)]
files = {'file': (uploaded_filename[0], str(eventlog_data))}
print(files)
requests.post(MIDDLEWARE_ENDPOINT+"data/upload-eventlog", files=files)
#Updates the dropdown "eventlog-dropdown"
files = requests.get(MIDDLEWARE_ENDPOINT + 'data/geteventloglist').json()
options = [{'label': i, 'value': i} for i in files]
return options
elif uploaded_contents is None:
files = requests.get(MIDDLEWARE_ENDPOINT + 'data/geteventloglist').json()
options = [{'label': i, 'value': i} for i in files]
return options
解析内容函数如下所示:
def parse_contents(contents, filename):
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')))
return df
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
return df
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
帖子“有效”。它发布了csv文件,并且csv文件正在存储在文件服务器上。但是,csv不再被逗号分隔并被截断:
69 FN322 Landing 2019-05-22 04:35 Berlin 12:20 4 12.333333
70 FN322 Baggage claim 2019-05-22 03:05 Berlin 01:40 5 1.666667
[71 rows x 7 columns]]
你们知道有什么简单的方法可以像Postman一样在Dash Upload组件中发布上传的文件名和内容吗?或至少如何保存所有文件内容?
非常感谢您,并祝您愉快!
答案 0 :(得分:0)
我知道了。这是由于以下几行代码:
`df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))`
要上传csv文件,我们不希望它成为文本流。它必须是类似字节的对象。代码:
decoded = base64.b64decode(content_string)
已经返回一个字节对象,这样我们只需要返回那个对象。因此,parse_contents()函数现在如下所示:
def parse_contents(contents, filename):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
return decoded
except Exception as e:
return html.Div([
'There was an error processing this file.'
])
请注意,我目前仅对csv文件感兴趣。这就是为什么我删除了xlsx部分。不幸的是,我不知道该代码是否也适用于xlsx文件。 代码
eventlog_data = [
parse_contents(c, n) for c, n in
zip(uploaded_contents, uploaded_filename)]
定义一个列表,其中已解码的字节对象是该列表中的第一个元素。因此,我们后请求的文件参数必须采用eventlog-data的第一个元素才能发送字节数据:
files = {'file': (uploaded_filename[0], eventlog_data[0])}
最终的回调如下:
@app.callback(
Output(component_id="eventlog-dropdown", component_property="options"),
[Input(component_id="upload-data", component_property="contents"),
Input(component_id="upload-data", component_property="filename")]
)
def upload_eventlog(uploaded_contents, uploaded_filename):
if uploaded_contents is not None:
eventlog_data = [
parse_contents(c, n) for c, n in
zip(uploaded_contents, uploaded_filename)]
files = {'file': (uploaded_filename[0], eventlog_data[0])}
requests.post(MIDDLEWARE_ENDPOINT+"predictivemonitor/upload-eventlog", files=files)
#Updates the dropdown "eventlog-dropdown"
files = requests.get(MIDDLEWARE_ENDPOINT + 'predictivemonitor/geteventloglist').json()
options = [{'label': i, 'value': i} for i in files]
return options
elif uploaded_contents is None:
#Still updates the dropdown "eventlog-dropdown" even if the content is empty
files = requests.get(MIDDLEWARE_ENDPOINT + 'predictivemonitor/geteventloglist').json()
options = [{'label': i, 'value': i} for i in files]
return options