ArcGis系列-java发布GP分析结果(带样式)

1,前言

继上一篇 ArcGis系列-java调用GP分析 ,已经实现了gp工具的发布,调用,轮询,并已经分别保存好发布地图服务所需的矢量数据json,栅格数据tif文件和样式文件

要将gp分析的结果发布为图层供前端展示,基础的python环境还是跟发布空间表一样,
实现思路基本一样,同样是用本地的空项目构添加图层构建草稿文件上传发布

2,java代码

如果调用发布的python执行成功,先在ArcGIS Enterprise控制台的内容去看下发布地址,
再在getPublishLayerUrl方法中拼接正确的发布地址

/**
     * 调用python发布图层到arcgis
     * @param dir 图层及样式文件临时目录
     * @param host
     * @param name
     * @param password
     * @param serviceName 图层服务名称
     * @return
     * @throws Exception
     */
    public String publishLayerToArcgis(String dir, String host, String name, String password, String serviceName) throws Exception {
        //host = host.replace("https","http");
        dir = dir.replace("\\","/");
        List params = new ArrayList<>();
        params.add("cmd.exe");
        params.add("/c");
        params.add("python");
        //python全路径
        String pyScriptName = scriptLocation + File.separator + PY_PUBLISH_LAYER;
        params.add(pyScriptName);
        params.add(dir);
        params.add(host);
        params.add(name);
        params.add(password);
        params.add(serviceName);
        String[] arr = params.toArray(new String[params.size()]);
        log.info("发布gp结果参数:{}", Arrays.toString(arr));
        int i = execSync(pyScriptName, arr);
        if (i == 0) {
            return getPublishLayerUrl(host, serviceName);
        } else {
            throw new Exception("调用" + scriptLocation + PY_PUBLISH_LAYER + "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 errorString = read(fileName, errorReader);
            log.info("读取python文件 fileName={}  errorString={}", fileName, errorString);
        });

        taskPool.submit(() -> {
            // 脚本执行正常时的输出信息
            BufferedReader inputReader = null;
            inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            List 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代码

在项目中分别遍历json文件,和tif文件,全部添加到新项目中,然后创建草稿;
因为是以gp分析id作为serverName,前端允许重复分析,所以发布时必须设置覆盖

# -*- coding: UTF-8 -*-
import arcpy
import os
import sys
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 = "layer_project_" + str(calendar.timegm(time.gmtime()))
targetProjectPath = os.path.join(projectDir, targetProject)
aprxName = "MyProject2.aprx"
gdbName = "MyProject2.gdb"


def publish_layers(temp_dir, host, name, password, service_name):
    arcpy.env.workspace = targetProjectPath
    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中的哪个地图下

    json_dir = os.path.join(temp_dir, "json")
    file_list = os.listdir(json_dir)
    for file in file_list:
        # 利用os.path.join()方法取得路径全名,并存入cur_path变量,否则每次只能遍历一层目录
        json_file_path = os.path.join(json_dir, file)
        feature_name = file.split(".")[0]
        arcpy.conversion.JSONToFeatures(json_file_path, os.path.join(gdbName, feature_name))
        aprx_map.addDataFromPath(os.path.join(targetProjectPath, gdbName, feature_name))

    #aprx_map.addDataFromPath("D:\\ITS\\map\\layerparam\\dem1.tif")
    json_dir = os.path.join(temp_dir, "tif")
    for subdir, dirs, files in os.walk(json_dir):
        for file in files:
            tifpath = os.path.abspath(os.path.join(subdir, file))
            if tifpath.endswith(".tif"):  # 如果文件后缀是tif
                aprx_map.addDataFromPath(tifpath)
            else:
                os.remove(tifpath)  # 删除该文件

    # 遍历图层添加样式
    layers = aprx_map.listLayers()
    for layer in layers:
        layer_name = arcpy.Describe(layer).file + ".lyrx"
        layer_name = layer_name.replace(".tif", "")
        print(layer_name)
        style_path = os.path.join(temp_dir, "style", layer_name)
        if os.path.exists(style_path):
            arcpy.ApplySymbologyFromLayer_management(layer, style_path)

    aprx.save()

    # Sign in to portal
    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 = "FEDERATED_SERVER"
    sd_draft = m.getWebLayerSharingDraft(server_type, "MAP_IMAGE", 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.overwriteExistingService=service_name
    sd_draft.portalFolder = "gptest"
    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)
    arcpy.UploadServiceDefinition_server(sd_output_filename, sd_draft.federatedServerUrl, service_name, None, None, "gptest",None, True, None, True, None, None)

    print("Finish Publishing")


if __name__ == '__main__':
    a = []
    for i in range(1, len(sys.argv)):
        print("arg:" + sys.argv[i])
        a.append(sys.argv[i])
    publish_layers(a[0], a[1], a[2], a[3], a[4])
    #publish_layers("D:/ITS/map/layerparam/44bgexhvc10000", "https://aaa.bbbb.com/arcgis", "name", "password","44bgexhvc10000")

    # shutil.rmtree(a[0])

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
ArcGis系列-java发布GP分析结果(带样式)_第1张图片

你可能感兴趣的:(GIS,arcgis,java,python,gp分析,发布分析结果)