我有一个
shiny
应用程序,它使用 folium
在地图上显示多个图层。
我想让用户能够将其中一个图层(线串地理数据框)下载为地理包文件。
这是我到目前为止的代码:
# relevant imported packages
from shiny import App, render, ui, reactive
import pandas as pd
import geopandas as gpd
# code in the ui for the download button
ui.download_button(id="downloadRoute", label="Get the route file"),
# code in the server function
@output
@render.download
def downloadRoute():
result_value = result()
route = result_value['route_detailed']
with io.BytesIO() as buffer:
route.to_file(buffer, driver='GPKG')
buffer.seek(0)
return ui.download(filename="my_route.gpkg", file=buffer.read(), content_type="application/geopackage+sqlite3")
我已经验证
route
实际上是一个有效的地理数据框。如果我在shiny之外下载它,它就是一个有效的geopackage。
在闪亮的情况下,单击下载按钮不会在用户界面上执行任何操作。它只在控制台中打印此错误:
500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "pyogrio\_io.pyx", line 1268, in pyogrio._io.ogr_create
File "pyogrio\_err.pyx", line 177, in pyogrio._err.exc_wrap_pointer
pyogrio._err.CPLE_OpenFailedError: sqlite3_open(<_io.BytesIO object at 0x000002494BFCE3E0>) failed: unable to open database file
我做错了什么?还有其他方法可以实现这一目标吗?
顺便说明一下,自 v0.6.0
起,不再需要
@output
装饰器 。关于下载问题,您(必须?)在render.download
中生成缓冲区的值,如下所示:
from io import BytesIO
from shiny import App, render, ui
import geopandas as gpd
from shapely import LineString
app_ui = ui.page_fluid(
ui.download_button(id="downloadRoute", label="Download as GPKG")
)
route = gpd.GeoDataFrame(geometry=[LineString([(0, 0), (1, 0)])])
def server(input):
@render.download(
filename="file.gpkg",
# media_type="application/geopackage+sqlite3", # optional
)
def downloadRoute():
with BytesIO() as buff:
route.to_file(buff, driver="GPKG")
yield buff.getvalue()
app = App(app_ui, server)
演示在shinylive: