You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Flask向GeoServer程序化上传.tiff栅格数据(无需GeoServer界面)

程序化通过Flask向GeoServer上传TIFF栅格数据实现方案

核心思路

利用GeoServer提供的REST API完成上传与发布,无需依赖Web界面。Flask作为中间层接收前端上传的TIFF文件,再调用GeoServer的REST接口完成数据上传和图层发布。


前提准备

  1. 确认GeoServer已启用REST服务(默认启用,可访问http://<geoserver-host>:8080/geoserver/rest验证)。
  2. 准备GeoServer管理员账号(默认admin/geoserver)。
  3. 提前创建目标工作区(Workspace),或通过代码自动创建。

实现步骤与代码

1. 安装依赖

pip install flask requests

2. Flask完整实现代码

from flask import Flask, request, jsonify
import requests
from requests.auth import HTTPBasicAuth

app = Flask(__name__)

# 配置GeoServer参数,替换为你的实际信息
GEOSERVER_CONFIG = {
    "url": "http://localhost:8080/geoserver",
    "username": "admin",
    "password": "geoserver",
    "workspace": "my_workspace",
    "coveragestore": "my_geotiff_store",  # 存储TIFF的数据存储名称
    "store_path": "file:///opt/geoserver/data_dir/data/my_workspace/my_geotiff_store"  # 数据存储物理路径,需保证GeoServer有写入权限
}

def create_geotiff_store():
    """自动创建GeoTIFF类型的数据存储(不存在则创建)"""
    create_url = f"{GEOSERVER_CONFIG['url']}/rest/workspaces/{GEOSERVER_CONFIG['workspace']}/coveragestores"
    headers = {"Content-type": "text/xml"}
    store_xml = f"""<dataStore>
        <name>{GEOSERVER_CONFIG['coveragestore']}</name>
        <connectionParameters>
            <entry key="url">{GEOSERVER_CONFIG['store_path']}</entry>
            <entry key="create spatial index">true</entry>
        </connectionParameters>
    </dataStore>"""
    
    try:
        response = requests.post(
            create_url,
            auth=HTTPBasicAuth(GEOSERVER_CONFIG['username'], GEOSERVER_CONFIG['password']),
            headers=headers,
            data=store_xml
        )
        # 存储已存在时返回409,属于正常情况
        if response.status_code not in [201, 409]:
            response.raise_for_status()
        return True
    except requests.exceptions.RequestException as e:
        print(f"创建数据存储失败: {str(e)}")
        return False

@app.route('/upload-tiff', methods=['POST'])
def upload_and_publish_tiff():
    # 检查上传文件合法性
    if 'tiff_file' not in request.files:
        return jsonify({"error": "未上传文件"}), 400
    tiff_file = request.files['tiff_file']
    if tiff_file.filename == '':
        return jsonify({"error": "未选择文件"}), 400
    if not tiff_file.filename.lower().endswith(('.tiff', '.tif')):
        return jsonify({"error": "仅支持TIFF格式文件"}), 400

    # 确保数据存储存在
    if not create_geotiff_store():
        return jsonify({"error": "数据存储创建失败"}), 500

    # 1. 上传TIFF文件到GeoServer数据存储
    upload_url = f"{GEOSERVER_CONFIG['url']}/rest/workspaces/{GEOSERVER_CONFIG['workspace']}/coveragestores/{GEOSERVER_CONFIG['coveragestore']}/file.geotiff"
    upload_headers = {"Content-type": "image/tiff"}
    
    try:
        upload_response = requests.put(
            upload_url,
            auth=HTTPBasicAuth(GEOSERVER_CONFIG['username'], GEOSERVER_CONFIG['password']),
            headers=upload_headers,
            data=tiff_file.read()
        )
        upload_response.raise_for_status()
    except requests.exceptions.RequestException as e:
        return jsonify({"error": f"文件上传失败: {str(e)}", "status": upload_response.status_code}), 500

    # 2. 发布为覆盖层(Coverage)
    coverage_name = tiff_file.filename.split('.')[0]
    publish_url = f"{GEOSERVER_CONFIG['url']}/rest/workspaces/{GEOSERVER_CONFIG['workspace']}/coveragestores/{GEOSERVER_CONFIG['coveragestore']}/coverages"
    publish_headers = {"Content-type": "text/xml"}
    coverage_xml = f"""<coverage>
        <name>{coverage_name}</name>
        <nativeName>{tiff_file.filename}</nativeName>
        <title>{coverage_name}</title>
        <srs>EPSG:4326</srs> <!-- 替换为你的TIFF实际坐标系 -->
    </coverage>"""

    try:
        publish_response = requests.post(
            publish_url,
            auth=HTTPBasicAuth(GEOSERVER_CONFIG['username'], GEOSERVER_CONFIG['password']),
            headers=publish_headers,
            data=coverage_xml
        )
        publish_response.raise_for_status()
    except requests.exceptions.RequestException as e:
        return jsonify({"error": f"图层发布失败: {str(e)}", "status": publish_response.status_code}), 500

    return jsonify({"message": f"TIFF文件上传并发布成功,图层名称: {coverage_name}"}), 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

关键注意事项

  • 路径权限:确保store_path指向的目录GeoServer进程有写入权限(Linux下可执行chown -R geoserver:geoserver <目录路径>)。
  • 坐标系匹配:代码中EPSG:4326需替换为TIFF文件实际坐标系,否则可能导致图层无法正常显示。
  • 接口测试:用curl或Postman发送测试请求:
    curl -X POST -F "tiff_file=@/path/to/your/file.tiff" http://localhost:5000/upload-tiff
    
  • 错误扩展:可根据需求添加日志记录、更精细的异常捕获逻辑。

内容的提问来源于stack exchange,提问作者Zarabotok 04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 00:42:37