ArcGis系列-java发布空间表为要素服务(feature)

news2024/11/25 12:31:03

1,实现思路

  1. 使用java调用cmd命令执行python脚本
  2. python环境使用arcgis pro安装目录下的 \ArcGIS\Pro\bin\Python\envs\arcgispro-py3
  3. 发布数据库表前需要先用创建数据库的sde文件(创建sde文件不需要连接arcgis)
  4. 发布表时,先在本地的空项目模板中添加数据库表作为图层,然后上传发布这个项目

2,java实现

2.1 调用入口

     /**
     * 创建数据库连接文件,传入数据库连接相关对象
     * 保存路径在python中设置
     *
     * @param userDbInfo
     */
    public void createArcgisSde(ExternalDataBaseDO userDbInfo) {
        List<Object> params = new ArrayList<>();
        params.add("cmd.exe");
        params.add("/c");
        params.add("python");
        //创建sde的python脚本路径
        String pyScriptName = scriptLocation + File.separator + PY_CREATE_SDE;
        params.add(pyScriptName);
        params.add(userDbInfo.getHost());
        params.add(userDbInfo.getPort());
        params.add(userDbInfo.getDataBaseName());
        params.add(userDbInfo.getUserName());
        params.add(userDbInfo.getPassWord());
        params.add(userDbInfo.getId());
        String[] arr = params.toArray(new String[params.size()]);
        int i = execSync(pyScriptName, arr);
        if (i != 0) {
            log.error("调用" + scriptLocation + PY_CREATE_SDE + "python异常!");
        }
    }

     /**
     * 调用python发布sqlserver数据库要素类到arcgis
     * @param sde sde全路径  D:\\ITS\\itsPython\\192.168.10.153.sde
     * @param host arcgis的url https://aaa.myarcgis.com/arcgis
     * @param name arcgis用户名 aaa
     * @param password arcgis密码 xxxx
     * @param table 要发布的表名 SD
     * @return
     * @throws Exception
     */
    public String publishTableToArcgis(String sde, String host, String name, String password, String table) throws Exception {
        host = host.replace("https", "http");
        host = host.replace(":6443", "");
        sde = sde.replace("\\", "/");
        List<Object> params = new ArrayList<>();
        params.add("cmd.exe");
        params.add("/c");
        params.add("python");
        String pyScriptName = scriptLocation + File.separator + PY_PUBLISH_TABLE;
        params.add(pyScriptName);
        params.add(sde);
        params.add(host);
        params.add(name);
        params.add(password);
        params.add(table);
        String[] arr = params.toArray(new String[params.size()]);
        log.info("发布空间表参数:{}", Arrays.toString(arr));
        //publish_single_table("D:\\ITS\\itsPython\\192.168.10.153.sde", "https://lzw.gis107.com/arcgis", "lzwpro", "lzwpro123", "dbo.SD")
        int i = execSync(pyScriptName, arr);
        if (i == 0) {
            //拼接发布地址 https://lzw.gis107.com/server/rest/services/SD/MapServer
            return getPublishTableUrl(host, table);
        } else {
            log.error("发布表失败:{}", i);
            return "error";
        }
    }

2.2 创建一个异步任务

执行python时可能会执行很久,这是一个 通用的方法,需要监听脚本执行状态

private int execSync(String fileName, String params[]) throws IOException {
        log.info("同步读取python文件 init fileName={}", fileName);
        Process process;
        if (OS.startsWith("Windows")) {
            // windows执行脚本需要使用 cmd.exe /c 才能正确执行脚本
            process = new ProcessBuilder(params).
                    start();
        } else {
            // linux执行脚本一般是使用python3 + 文件所在路径
//            process = new ProcessBuilder("python3", LINUX_PATH + fileName, params).start();
            process = new ProcessBuilder(params).start();
        }

        taskPool.submit(() -> {
            log.info("读取python文件 开始 fileName={}", fileName);
            BufferedReader errorReader = null;
            // 脚本执行异常时的输出信息
            errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            List<String> errorString = read(fileName, errorReader);
            log.info("读取python文件 fileName={}  errorString={}", fileName, errorString);
        });

        taskPool.submit(() -> {
            // 脚本执行正常时的输出信息
            BufferedReader inputReader = null;
            inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            List<String> returnString = read(fileName, inputReader);
            log.info("读取python文件 fileName={}  returnString={}", fileName, returnString);
        });

        try {
            boolean res = process.waitFor(1L, TimeUnit.DAYS);
            if (res) {
                int i = process.exitValue();
                log.info("执行python文件 fileName={} == 结束 == {}", fileName, i);
                return i;
            }
            return 1;
        } catch (InterruptedException e) {
            log.error("同步读取python文件 fileName=" + fileName + " 等待结果返回异常", e);
            return 1;
        }
    }

3,python脚本

3.1 创建sde文件

import arcpy, os

# 从用户输入获取连接参数

def create_sde(ip, port, dbname, username, password, dbId):
    # 创建临时 SDE 连接文件
    temp_sde = os.path.join(arcpy.env.scratchFolder, "temp.sde")
    arcpy.Delete_management(temp_sde)
    arcpy.CreateDatabaseConnection_management(os.path.dirname(temp_sde),
                                               os.path.basename(temp_sde),
                                               "SQL_SERVER", ip+","+port, "DATABASE_AUTH",
                                               username, password, "SAVE_USERNAME",
                                               dbname)
    #arcpy.CreateDatabaseConnection_management("C:/temp", "myDatabase.sde", "SQL_SERVER", "myServer", "DATABASE_AUTH", "myUser", "myPassword", "#", "myDatabase", "#", "#", "#", "#", "#")
    # 复制并重命名临时 SDE 连接文件到指定位置D:\ITS\map\sde
    output_sde = "D:\\ITS\\map\\sde\\" + dbId + ".sde"
    if os.path.isfile(output_sde):
        os.remove(output_sde)
    arcpy.Copy_management(temp_sde, output_sde)

    # 删除临时 SDE 连接文件
    arcpy.Delete_management(temp_sde)

if __name__ == '__main__':
    a = []
    for i in range(1, len(sys.argv)):
        print("arg:" + sys.argv[i])
        a.append(sys.argv[i])

    create_sde(a[0], a[1], a[2], a[3], a[4], a[5])
    #create_sde("192.168.10.153", "1433", "测试中文数据库", "sa", "admin888888", "测试sde文件名")

3.2 发布表

  • 发布表是在本地一个空的项目作为模板(D:\ITS\map\MyProject2),添加数据库表,生成草稿文件来发布;
  • 空项目文件可以使用arcgis pro创建项目删除所有地图得到;
  • 添加表图层是要根据空间表实际类型来,区分矢量表和栅格表;
  • 指定发布目录是要确保目录在arcgis已创建,发布图层这里设置的覆盖且直接公开.
# -*- coding: UTF-8 -*-
import arcpy
import sys
import os
import calendar
import time
import shutil

# 将标准输出和标准错误输出都重定向到同一个文件中
log_file = open("D:/ITS/pythonlog.txt", "w")
sys.stdout = log_file
sys.stderr = log_file

# 覆盖
arcpy.env.overwriteOutput = True

projectDir = r"D:\ITS\map"
templateProject = "MyProject2"
# 创建临时目录
targetProject = "project_" + str(calendar.timegm(time.gmtime()))
targetProjectPath = os.path.join(projectDir, targetProject)
aprxName = "MyProject2.aprx"


def publish_single_table(sde, host, name, password, table):
    arcpy.env.workspace = sde
    # 数据库表追加feature前缀,用来区分要素类型,后期单表会发布成map服务
    service_name = "feature_" + table
    shutil.copytree(os.path.join(projectDir, templateProject), targetProjectPath)
    mpmath = os.path.join(targetProjectPath, aprxName)
    aprx = arcpy.mp.ArcGISProject(mpmath)  # aprx存储路径
    aprx_map = aprx.listMaps("*")[0]  # 要将数据添加到aprx中的哪个地图下
    # 先从矢量表找目标表,找不到就去栅格表找
    sde_list = arcpy.ListFeatureClasses()
    print("遍历矢量图层!")
    for item in sde_list:
        # 不确定sde文件中每张表的格式,有可能是 库名.组织.表名,也可能是 组织.表名,只匹配最后表名
        if item.split(".")[-1] == table:
            print("添加图层:" + sde + "/" + item)
            aprx_map.addDataFromPath(sde + "/" + item)
            break
    else:
        print('矢量图层没找到 ' + table)
        # 如果未找到目标则遍历栅格图层
        sde_list=arcpy.ListRasters()
        print("遍历栅格图层!")
        for item in sde_list:
            if item.split(".")[-1] == table:
                aprx_map.addDataFromPath(sde + "/" + item)
                break
        else:
            print('栅格图层未找到 ' + table)
            raise Exception(table + "  table is not find")
    # lyrx = arcpy.mp.LayerFile("D:\\ITS\\map\\style\\县界.lyrx")
    # listLayers = aprxMap.listLayers()
    # for layer in listLayers:
    #     arcpy.ApplySymbologyFromLayer_management(layer, "D:\\ITS\\map\\style\\县界.lyrx")
    aprx.save()

    # Sign in to portal
    a = arcpy.SignInToPortal(host, name, password)

    # Set output file names
    out_dir = os.path.join(targetProjectPath, "out")
    os.makedirs(out_dir)
    sd_draft_filename = service_name + ".sddraft"
    sd_draft_output_filename = os.path.join(out_dir, sd_draft_filename)
    sd_filename = service_name + ".sd"
    sd_output_filename = os.path.join(out_dir, sd_filename)

    # Reference map to publish
    # aprx = arcpy.mp.ArcGISProject("D:\\ITS\\map\\MyProjectMyProject.aprx")
    m = aprx.listMaps()[0]

    # Create FeatureSharingDraft and set metadata, portal folder, and export data properties
    server_type = "HOSTING_SERVER"
    sd_draft = m.getWebLayerSharingDraft(server_type, "FEATURE", service_name)
    hosts = host.split("/")
    b = hosts[len(hosts) - 1]
    print(b)
    sd_draft.federatedServerUrl = host.replace(b, "server")
    sd_draft.credits = "These are credits"
    sd_draft.description = "This is description"
    sd_draft.summary = "This is summary"
    sd_draft.tags = "tag1, tag2"
    sd_draft.useLimitations = "These are use limitations"
    sd_draft.serverFolder = "gptest"
    sd_draft.allowExporting = True
    sd_draft.overwriteExistingService = True

    # Create Service Definition Draft file
    sd_draft.exportToSDDraft(sd_draft_output_filename)

    # Stage Service
    print("Start Staging")
    arcpy.StageService_server(sd_draft_output_filename, sd_output_filename)

    # Share to portal
    print("Start Uploading")
    arcpy.UploadServiceDefinition_server(sd_output_filename, sd_draft.federatedServerUrl, service_name, None, None, "gptest",None, True, None, True, None, None)

    print("Finish Publishing")
    # https://lzw.gis107.com/server/rest/services/ROAD/MapServer


if __name__ == '__main__':
    a = []
    for i in range(1, len(sys.argv)):
        print("arg:" + sys.argv[i])
        a.append(sys.argv[i])
    #执行一些操作并输出信息或错误信息
    publish_single_table(a[0], a[1], a[2], a[3], a[4])
    #publish_single_table("D:\\ITS\\map\\sde\\192.168.10.153.sde", "http://lzw.server.com/arcgis", "lzwpro", "lzwpro123", "STBHHX")

    #shutil.rmtree(targetProjectPath)

4,可能会遇到的问题

如果arcgis pro的版本与arcgis的服务版本不兼容,pro下的python也会报一些奇怪的错,我使用的3.0.1的pro和10.6的arcgis;
如果执行python脚本包url问题,可以切换https与http试下,与arcgis的版本有关;
调试时在arcgis的manage可以查看执行日志 https://aaa.myarcgis.com:6443/arcgis/manager
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/587799.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

界面组件Telerik UI for WPF可轻松实现直方图,让数据可视化更简单

Telerik UI for WPF拥有超过100个控件来创建美观、高性能的桌面应用程序&#xff0c;同时还能快速构建企业级办公WPF应用程序。UI for WPF支持MVVM、触摸等&#xff0c;创建的应用程序可靠且结构良好&#xff0c;非常容易维护&#xff0c;其直观的API将无缝地集成Visual Studio…

word如何设置页码?教您快速掌握!

案例&#xff1a;论文排版时&#xff0c;需要对页码进行编号&#xff0c;但我不知道怎么操作。我想如何快速设置word页码&#xff0c;有没有小伙伴可以分享一下方法&#xff1f; word是一款广泛使用的文字处理软件&#xff0c;许多人在撰写论文、报告或其他文档时都需要对页面…

StableDiffusion教程(3) - 模型安装

StableDiffusion模型安装 1. 搜索模型 打开C站或者LibLibAI模型站下载模型 C站地址&#xff1a;https://civitai.com/ LibLibAI模型站地址&#xff1a;LiblibAi - 中国领先原创AI模型分享社区 2. 下载模型 在模型详情页面&#xff0c;点击下载即可下载模型 3. 把模型放进S…

《A New General Type-2 Fuzzy Predictive Scheme for PID Tuning》翻译,2021年

《一种新的用于PID整定的通用2型模糊预测方案》 摘要 PID控制器在各种工业应用中被广泛使用。但是&#xff0c;在许多有噪音的问题中&#xff0c;需要强有力的方法来优化PID参数。在本文中&#xff0c;介绍了一种通过模型预测控制和广义 2 型模糊逻辑系统调整比例-积分-微分参数…

一步一步的指导在自定义数据集上训练 YOLO NAS

本教程将一步一步指导实验 YOLO-NAS 的进行完整的数据集训练。 YOLO-NAS是目前最新的YOLO物体检测模型。从一开始,它就在准确性方面击败了所有其他 YOLO 模型。与之前的 YOLO 模型相比,经过预训练的 YOLO-NAS 模型可以更准确地检测到更多的对象。但是我们如何在自定义数据集…

MySQL 条件判断函数

文章目录 条件判断函数if()函数ifnull() 函数case() 函数1. 成功匹配其中一条 when 分支3. 所有 when 分支匹配失败&#xff0c;进入 else 默认分支。 条件判断函数 关于条件判断函数&#xff0c;主要介绍以下三种&#xff1a; if()函数 if() 函数&#xff0c;其基本语法如下…

D4-4 基本分页存储管理方式(第二节课)

目录 4.4.4 两级和多级页表 1、两级页表的引入 2、两级页表 4.4.6 对换 1、外存的划分 2、对换区管理 3、进程的换出与换入 4.4.4 两级和多级页表 1、两级页表的引入 可以采用以下方法来解决这一问题&#xff1a; 采用离散分配方式来解决难以找到一块连续的大内存空…

SaaS突围战,用友走了8年,金蝶却用了10年,成果却被捷足先登

“南金蝶北用友”得风口在哪里&#xff1f; 众所周知&#xff0c;在企业软件管理市场中&#xff0c;一直有着这样的说法“北用友南金蝶”&#xff0c;足以可见&#xff0c;两家企业在市场中的份量。两家公司最初都是以财务软件起家&#xff0c;关于创始人王文京和徐少春的创业…

PyTorch-模型验证

目的&#xff1a;利用已经训练好的网络模型&#xff0c;输入数据进行测试。&#xff08;相当于将其运用于真实场景中&#xff09; Cifar-10分类&#xff1a; test1&#xff1a;放入一张狗狗的图片 进行验证&#xff1a;test.py import torch import torchvision from PIL imp…

gaussDB的schema创建查询,及其查询下面的表列

pg_catalog.pg_namespace来查看当前数据库中全部的Schema select oid,* from pg_catalog.pg_namespace; 创建schema create schema gs_dqms 显示当前使用的schema SHOW search_path; 切换当前schema SET search_path TO gs_dqms; 查看Schema---- dgp_sd下所有表的大小&…

2023年软件设计师上午试题及参考答案

2023年上半年 软件设计师 上午试卷 加粗为参考答案,不一定能全对 &#xff08;考试时间9:00~11:30共150分钟&#xff09; 请按下述要求正确填写答题卡 1.在答题卡的指定位置上正确填写你的姓名和准考证号&#xff0c;并粘贴考生条形码。 2.本试卷的试题中共有75个空格&#…

蓝牙资讯|2023 年 Q1 全球智能音频设备出货量8672万部

市场调研机构 Canalys 公布了 2023 年第一季度全球个人智能音频设备出货量报告。 报告显示 2023 年第一季度全球个人智能音频设备出货量跌至 8672 万部&#xff0c;同比下降 15%。其中 TWS 真无线耳机出货量下滑至 6158 万部&#xff0c;同步下降 10%。其中&#xff0c;苹果&…

基础知识铺垫

目录 一、HTTP 1.http协议 2.http协议的工作原理 3.http的请求 请求行 请求头 请求体 4.http的响应 响应行 5.get和post请求方法 6.get和post的区别 回退 请求响应速度 二、MYSQL 1.创建数据库 2.创建表 3.添加数据 4.删除数据 5.更新数据 6.查询数据 7.常…

Vue3+express实现element-plus组件upload上传图片携带data

需求背景&#xff1a;有多个轮播图需要单独上传&#xff0c;需要用data去区分上传的是哪一个轮播图 添加轮播图页面如下图所示&#xff1a; 实现效果&#xff1a; 实现思路及需要了解一下信息 ①每一个轮播图应在数据库中有相对应的字段&#xff0c;如下所示&#xff1a; 需…

【数据仓库】即席查询

文章目录 定义特点OLTP、OLAP、即席查询(ad hoc query)区别与联系相关框架Kylin来源 定义 即席查询&#xff08;Ad Hoc&#xff09;是用户根据自己的需求&#xff0c;灵活的选择查询条件&#xff0c;系统能够根据用户的选择生成相应的统计报表。即席查询与普通应用查询最大的不…

CompletableFuture的简单使用

原文地址&#xff1a;CompletableFuture原理与实践-外卖商家端API的异步化 CompletableFuture的介绍&#xff1a; CompletableFuture是Java 8中引入的一种基于Future的异步编程机制。与传统的Future相比&#xff0c;CompletableFuture提供了更多的操作链支持&#xff0c;并且…

skywalking 9.x入门(二) skywalking全链路tid追踪

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 背景 继上次我们对skywalking整体架构作了一些了解&#xff0c;然后就是学习了spring boot项目如何基于agent接入skywalking 这次我们要实现的是spring boot项目…

USB | 查询usb设备占用带宽

USB | 查询usb设备占用带宽 请教一下windows下有什么工具能查询usb设备占用带宽吗&#xff1f;Linux上有usbtop&#xff0c;windows有类似工具吗 DeviceMonitoringStudio设备监控工具的使用

好用的自动化框架-Allure

概述 报告主要包含总览、类别、测试套件、图表、时间刻度、功能、包等7大部分&#xff0c;支持自定义诸多信息&#xff0c;包括附件添加、缺陷链接、案例链接、测试步骤、Epic、Feature、Story、Title、案例级别等&#xff0c;相当强大。 allure与pytest的结合使用可以呈现完…

华为OD机试真题B卷 Java 实现【求小球落地5次后所经历的路程和第5次反弹的高度】,附详细解题思路

一、题目描述 假设一个球从任意高度自由落下&#xff0c;每次落地后反跳回原高度的一半; 再落下, 求它在第5次落地时&#xff0c;共经历多少米?第5次反弹多高&#xff1f; 数据范围&#xff1a;输入的小球初始高度满足 1 \le n \le 1000 \1≤n≤1000 &#xff0c;且保证是一…