如何通过Dash上传FMU文件并获取可被函数识别的文件路径
问题描述
- 需求:允许用户上传FMU文件(可视为压缩文件夹),并传递给仅接受文件路径字符串的函数
load_fmu使用。 - 限制条件:
load_fmu仅支持文件路径字符串作为输入,不接受字节流、内存对象等其他类型。- Dash的Upload组件出于安全考虑,仅返回文件名,不返回用户本地的文件路径,且该文件名无法被
load_fmu识别。
- 核心疑问:如何加载FMU这类不支持decode方法的文件?能否获取Upload组件存入内存的文件的路径字符串供
load_fmu访问?
解决方案
由于load_fmu必须依赖真实的文件系统路径才能工作,而Upload组件仅提供文件的base64编码内容,唯一可行的方案是将上传的字节内容写入服务器本地的临时文件,再将临时文件的路径传给load_fmu。具体步骤:
- 解码Upload组件传来的base64字符串,得到文件的字节流。
- 在服务器本地创建带
.fmu后缀的临时文件,将字节流写入该文件。 - 把临时文件的完整路径作为参数传入
load_fmu。 - 加载完成后可删除临时文件,避免占用服务器磁盘空间。
修改后的可运行代码
from pyfmi import load_fmu from dash import Dash, dcc, html, Input, Output, State, callback import base64 import tempfile import os app = Dash(__name__) app.layout = html.Div([ dcc.Upload( id='upload-fmu', children=html.Div([ '拖拽或 ', html.A('选择FMU文件') ]), style={ 'width': '10%', 'height': '40px', 'lineHeight': '60px', 'borderWidth': '1px', 'borderStyle': 'dashed', 'borderRadius': '5px', 'textAlign': 'center', 'margin': '10px' }, multiple=True ), html.Div(id='output-fmu-upload'), ]) def parse_contents(contents, filename, date): content_type, content_string = contents.split(',') decoded = base64.b64decode(content_string) try: if filename.endswith('.fmu'): # 创建临时文件,保留.fmu后缀确保格式被识别 with tempfile.NamedTemporaryFile(delete=False, suffix='.fmu') as tmp_file: tmp_file.write(decoded) tmp_file_path = tmp_file.name # 通过临时文件路径加载FMU模型 model = load_fmu(tmp_file_path) print(f"成功加载模型:{model.get_name()}") # 使用完毕后删除临时文件,释放磁盘空间 os.unlink(tmp_file_path) return html.Div([ html.H5(f"文件 {filename} 加载成功"), html.P(f"模型名称:{model.get_name()}"), html.P(f"上传时间:{date}") ]) except Exception as e: print(f"错误详情:{str(e)}") return html.Div([ f"处理文件 {filename} 时出错:{str(e)}" ]) @callback(Output('output-fmu-upload', 'children'), Input('upload-fmu', 'contents'), State('upload-fmu', 'filename'), State('upload-fmu', '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 if __name__ == '__main__': app.run(debug=True)
关键注意事项
- 必须使用真实文件路径:
load_fmu底层依赖文件系统操作,无法直接读取内存中的字节流(如io.BytesIO对象),因此写入临时文件是唯一可行方案。 - 临时文件管理:使用
delete=False确保文件在关闭后不会被自动删除,让load_fmu能正常访问;加载完成后通过os.unlink删除临时文件,避免磁盘占用。如果需要保留文件用于后续操作,可以移除删除逻辑,或添加定期清理机制。 - 文件后缀:创建临时文件时指定
suffix='.fmu',确保load_fmu能正确识别文件格式。
内容的提问来源于stack exchange,提问作者Scott G
相关产品推荐
相关产品推荐

