如何使用Jupyter Notebook和Voila为用户提供可下载的临时zip对象



我写了一个jupyter笔记本,我想用Voila渲染它来创建一个小的web应用程序/工具。该工具所做的是获得一个包含多个的Geojson文件并返回包含多个的ZIP文件。GeoJSON文件(每个多边形一个文件)。例如,如果用户上传一个包含20个多边形的GeoJSON文件(它们都在同一个文件中),那么输出应该是一个包含20个独立GeoJSON文件的ZIP文件——每个多边形一个文件。我可以在本地完成,并且ZIP文件会在需要时保存。

然而,我想渲染它使用Voila,以便它以后可以从任何地方工作,这意味着ZIP文件将被创建在内存中/在飞行中/作为一个缓冲区(不确定哪个术语是准确的),然后用户将能够下载ZIP文件,通过自动下载,或通过点击按钮或弹出窗口下载,这真的不重要在这里。

下面是我的代码片段(如果不够请告诉我):

def on_button_clicked(event):
with output:
clear_output()
df = gpd.GeoDataFrame().from_features(json.loads(upload.data[0])) # if the file is geojson
display(HTML(f'<h4><left>There are {len(df)} polygons in the file</left></h4>'))

# make results.zip in temp directory
# https://gist.github.com/simonthompson99/362404d6142db3ed14908244f5750d08
tmpdir = tempfile.mkdtemp()
zip_fn = os.path.join(tmpdir, 'results.zip')
zip_obj = zipfile.ZipFile(zip_fn, 'w')
for i in range(df.shape[0]):
if len(field_names_col.value)==0:
field_name = f'field_{str(i+1)}'
else:
field_name = df[field_names_col.value][i]
output_name = f'{field_name}.{output_format.value.lower()}'
df.iloc[[i]].to_file(f'{tmpdir}\{output_name}', driver=output_format.value)
for f in glob.glob(f"{tmpdir}/*"):
zip_obj.write(f, os.path.basename(f)) # add file to archive, second argument is the structure to be represented in zip archive, i.e. this just makes flat strucutre
zip_obj.close()
button_send.on_click(on_button_clicked)
vbox_result = widgets.VBox([button_send, output])

重要的部分在接近结尾的地方:

for f in glob.glob(f"{tmpdir}/*"):
zip_obj.write(f, os.path.basename(f)) # add file to archive, second argument is the structure to be represented in zip archive, i.e. this just makes flat strucutre
zip_obj.close()

遍历临时独立文件,并创建一个存储在zip_obj. ZIP目录中的临时ZIP文件(results.zip)。我该如何"推"?这个ZIP对象给用户下载使用Jupyter Notebook?

我试着使用(就在zip_obj.close()之前或之后):

local_file = FileLink(os.path.basename(f), result_html_prefix="Click here to download: ")
display(local_file)

但是当我用Voila:

渲染它时,我得到了一个错误

路径(results.zip)不存在。它可能还在进行中正在生成,或者您的路径可能不正确。

例如,要将它保存在本地,我这样做:

with zipfile.ZipFile('c:/tool/results.zip', 'w') as zipf:
for f in tmpdir.glob("*"):
zipf.write(f, arcname=f.name)

"我遍历了临时的独立文件,并创建了一个存储在zip_obj中的临时ZIP文件(results.zip)。我该如何"推"?这个ZIP对象给用户下载使用Jupyter Notebook?">

这里有一个制作下载链接的示例,它将显示在这里的Voila渲染中。(从这里学到的,虽然重点是文件上传。该示例还包括下载结果。)在这个答案的底部可以找到一个更简单的解释,转换为您的情况:

%%html
<a href="./voila/static/the_archive.zip" download="demo.xlsx">Download the Resulting Files as an Archive</a>

在答案的底部部分(目前换行符以下的所有内容)中说明了这两个选项用于不同类型的文件。

最新更新