Hei*_*ich 2 python django zip geopandas
我有一个与 Django GIS 相关的应用程序,用户可以在其中下载 shp 文件。我有 geopandas GeoDataFrame 对象。我可以轻松地将其转换为 zip 文件,然后在用户想要下载时将其读取给用户:
from django.http import HttpResponse
import geopandas as gpd
import shapely
import os
from zipfile import ZipFile
def download_shp_zip(request):
# just some random polygon
geometry = shapely.geometry.MultiPolygon([
shapely.geometry.Polygon([ (0, 0), (0, 1), (1, 1), (1, 0) ]),
shapely.geometry.Polygon([ (2, 2), (2, 3), (3, 3), (3, 2) ]),
])
# create GeoDataFrame
gdf = gpd.GeoDataFrame(data={'geometry':geometry}, crs='epsg:4326')
# some basename to save under
basename = 'basename'
# create folder for this session
os.mkdir(f"local_folder/{basename}")
# export gdf to this folder
gdf.to_file(f"local_folder/{basename}/{basename}.shp")
# this file now contains many files. just zip them
zipObj = ZipFile(f"local_folder/{basename}.zip", 'w')
# zip everything in the folder to the zip
for file in os.listdir(f"local_folder/{basename}"):
zipObj.write(f"local_folder/{basename}/{file}")
# create zip
zipObj.close()
# now delete the original files that were zipped
shutil.rmtree(f"local_folder/{basename}")
# now we can server the zip file to the user
filename = f'local_folder/{basename}.zip'
# check if file exists (just in case)
try:
fsock = open(filename, "rb")
except:
return HttpResponse(f"File '{basename}' Does Not Exist!",
content_type='text/plain')
# create response
response = HttpResponse(fsock, content_type='application/zip')
response['Content-Disposition'] = f'attachment; filename={basename}.zip'
return response
Run Code Online (Sandbox Code Playgroud)
此方法有效,但它将文件保存到本地存储,然后提供服务。但是,我想将它们保存到内存中,然后将其提供给用户。我见过人们使用 os.BytesIO 来做类似的事情。我一直在玩,但我无法完全找到任何适合我所寻找的东西。
同样,我有 GeoDataFrame。我想将其转换为 shapefile,然后将其压缩,然后将压缩的文件夹从内存提供给用户,而不将其写入本地存储。
可以使用tempfile创建文件并在服务后立即删除它。所以这不是您正在寻找的答案,但也许仍然有帮助。根据这个答案:
一旦文件处理程序关闭,由 tempfile 创建的任何文件都将被删除。在您的情况下,当您退出 with 语句时。
from django.http import HttpResponse
import geopandas as gpd
import shapely
import os
import tempfile
from zipfile import ZipFile
def download_shp_zip(request):
# just some random polygon
geometry = shapely.geometry.MultiPolygon([
shapely.geometry.Polygon([(0, 0), (0, 1), (1, 1), (1, 0)]),
shapely.geometry.Polygon([(2, 2), (2, 3), (3, 3), (3, 2)]),
])
# create GeoDataFrame
gdf = gpd.GeoDataFrame(data={'geometry': geometry}, crs='epsg:4326')
# some basename to save under
basename = 'basename'
# Convert to shapefile and serve it to the user
with tempfile.TemporaryDirectory() as tmp_dir:
# Export gdf as shapefile
gdf.to_file(os.path.join(tmp_dir, f'{basename}.shp'), driver='ESRI Shapefile')
# Zip the exported files to a single file
tmp_zip_file_name = f'{basename}.zip'
tmp_zip_file_path = f"{tmp_dir}/{tmp_zip_file_name}"
tmp_zip_obj = ZipFile(tmp_zip_file_path, 'w')
for file in os.listdir(tmp_dir):
if file != tmp_zip_file_name:
tmp_zip_obj.write(os.path.join(tmp_dir, file), file)
tmp_zip_obj.close()
# Return the file
with open(tmp_zip_file_path, 'rb') as file:
response = HttpResponse(file, content_type='application/force-download')
response['Content-Disposition'] = f'attachment; filename="{tmp_zip_file_name}"'
return response
Run Code Online (Sandbox Code Playgroud)
另一种选择是在 try-except 块内使用 return 语句,并在 finally 语句中删除文件:
# Return the zip file as download response and delete it afterwards
try:
with open(tmp_zip_file_path, 'rb') as file:
response = HttpResponse(file, content_type='application/force-download')
response['Content-Disposition'] = f'attachment; filename="{tmp_zip_file_name}"'
return response
finally:
os.remove(tmp_zip_file_path)
Run Code Online (Sandbox Code Playgroud)
为了获得更好的用户体验,您可以在下载开始之前使用加载 gif。
| 归档时间: |
|
| 查看次数: |
589 次 |
| 最近记录: |