我正在尝试使用 Python 从 GeoServer 下载 GeoTiff 文件。我在网上找到了一些关于此类事情的资源,但我无法完成这项任务。
例如,这里:https://gis.stackexchange.com/questions/181560/download-geotiff-from-geoserver似乎人们已经能够做我想做的事情,但他们没有解释他们的过程。
同样,这里接受的答案:如何从 python 获取 TIFF 图像适用于下载 GeoTiff,如 http://imgsrc.hubblesite.org/hu/db/images/hs-2006-01-a -hires_tif.tif,但 GeoServer 上没有 GeoTiffs 的下载链接。
任何帮助将不胜感激!
编辑:这里有一些关于我迄今为止所尝试的更多细节。 GeoServer 有一个 Rest API 服务器,位于本地 http://localhost:8080/geoserver/rest ,所以我最初尝试在 python 中访问这个 url,然后在“Layers”中下载我想要的 GeoTiff。然而,“Layers”中的每个文件都是一个html文件;我想知道是否有一个地方可以实际以编程方式访问 GeoTiff 文件。我认为这是问题的根源 - 虽然我不太确定如何以编程方式下载 GeoTiffs,但我必须首先能够在 GeoServer 中实际访问它们。
但就进展而言,我并没有取得多大进展。正如我上面提到的,我可以使用如何从 python 获取 TIFF 图像中的代码下载 GeoTiff,但我无法在 GeoServer 上为 GeoTiff 执行此操作。我对 GeoServer 和 GeoTiff 格式都很陌生,所以我不太确定如何解决这个问题。
正如您的链接问题的答案所示,您需要向GeoServer发出WCS请求以获取GeoTiff。
GeoServer 手册提供了WCS参考,可以帮助您了解如何继续操作。您还可以转到 GeoServer 安装的演示页面,并使用 WCS 请求构建器创建一个 XML 文件,您可以将其用作 Python 程序中的模板。
我的同事找到了解决这个问题的方法。使用下面的示例代码,我们可以从 GeoServer 下载 GeoTiff 文件。
from owslib.csw import CatalogueServiceWeb
import urllib
def getLinkByIDCWS(url, id, user, pwd):
csw = CatalogueServiceWeb(url, username=user, password=pwd)
csw.getrecordbyid(id=[id])
csw.records[id].references
link = csw.records[id].references[2]['url']
return link
def downloadImage(url, fileName):
urllib.request.urlretrieve(url, fileName)
url = "http://localhost:8080/geoserver/csw?service=CSW&version=2.0.2&request=GetRecords&typeNames=gmd:MD_Metadata&resultType=results&elementSetName=full&outputSchema=http://www.isotc211.org/2005/gmd"
record = "nurc:Arc_Sample"
name = "<user>"
pwd = "<pwd>"
link = getLinkByIDCWS(url, record, name, pwd)
print(link)
downloadImage(link, "test.arc")
通过这种方式,我设法从地理服务器获取每个栅格图层,调整图像的大小。对于desired_width 20000图像来说大约是1.5 Gb
from owslib.wcs import WebCoverageService
import urllib
import re
url_geoserver = "http://your_server/geoserver/ows"
ows = WebCoverageService(url_geoserver)
lst = list(ows.contents.keys()) #list of the layers
metadata_list = ows.contents.values() #list off metadata
your_lst = list(filter(lambda x: 'your_selected_layers' in x, lst)) # list of selected layers
layer_name = your_lst[0] # for example
crs_url = ows.contents[f'{layer_name}'].boundingboxes[0]['nativeSrs']
bbox = ows.contents[f'{layer_name}'].boundingboxes[0]['bbox']
width, height = calculate_dimensions(bbox,20000)
crs = extract_digits(crs_url)
layer_name = layer_name.replace('workspace_name','') # you need to get rid of the workspace, also there might be some other symbols
url = f'http://you_geoserver_address/geoserver/your_workspace/wms?service=WMS&version=1.1.0&request=GetMap&layers={layer_name}&bbox={bbox[0]}%2C{bbox[1]}%2C{bbox[2]}%2C{bbox[3]}&width={width}&height={height}&srs=EPSG%3A{crs}&styles=&format=image%2Fgeotiff'
filename = f'{layer_name}.tif'
downloadImage(url, filename)
def extract_digits(url):
match = re.search(r'\/(\d+)$', url)
if match:
return match.group(1)
else:
return None
def calculate_dimensions(bbox, desired_width):
minx, miny, maxx, maxy = bbox[0], bbox[1], bbox[2], bbox[3]
aspect_ratio = (maxx - minx) / (maxy - miny)
height = int(desired_width / aspect_ratio)
return desired_width, height
def downloadImage(url, fileName):
try:
urllib.request.urlretrieve(url, fileName)
print(f"Download completed: {fileName}")
except urllib.error.HTTPError as e:
print(f"HTTP Error: {e.code} - {e.reason}")
except Exception as e:
print(f"An error occurred while downloading the file: {e}")