ArcGis series-java release space table como servicio de entidades (característica)

1, realizar ideas

  1. Use java para llamar al comando cmd para ejecutar el script de python
  2. El entorno de python usa \ArcGIS\Pro\bin\Python\envs\arcgispro-py3 en el directorio de instalación de arcgis pro
  3. Antes de publicar la tabla de la base de datos, debe usar el archivo sde para crear la base de datos (la creación del archivo sde no necesita conectarse a arcgis)
  4. Al publicar una tabla, primero agregue la tabla de la base de datos como una capa en la plantilla de proyecto local vacía y luego cargue y publique el proyecto.

2, implementación de Java

2.1 Entrada de llamada

     /**
     * 创建数据库连接文件,传入数据库连接相关对象
     * 保存路径在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 Crear una tarea asíncrona

Puede llevar mucho tiempo ejecutar python. Este es un método general que necesita monitorear el estado de ejecución del script.

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, secuencia de comandos de Python

3.1 Crear archivo 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 Tabla de liberación

  • La tabla de lanzamiento es un proyecto vacío localmente como plantilla (D:\ITS\map\MyProject2), agrega una tabla de base de datos y genera un archivo borrador para publicar;
  • Los archivos de proyecto vacíos se pueden obtener utilizando arcgis pro para crear un proyecto y eliminar todos los mapas;
  • Agregar una capa de tabla es distinguir entre una tabla vectorial y una tabla ráster según el tipo real de tabla espacial;
  • Especificar el directorio de publicación es para garantizar que el directorio se haya creado en arcgis y que la capa de publicación se sobrescriba y se exponga directamente.
# -*- 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, problemas que pueden surgir

Si la versión de arcgis pro no es compatible con la versión de servicio de arcgis, python bajo pro también informará algunos errores extraños. Uso 3.0.1 pro y 10.6 arcgis; si ejecuta el problema de URL del paquete de secuencias de comandos de python, puede cambiar entre https
y Try http, está relacionado con la versión de arcgis;
al depurar, puede ver el registro de ejecución en la administración de arcgis https://aaa.myarcgis.com:6443/arcgis/manager
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/u012796085/article/details/130942956
Recomendado
Clasificación