1,实现思路
- 使用java调用cmd命令执行python脚本
- python环境使用arcgis pro安装目录下的 \ArcGIS\Pro\bin\Python\envs\arcgispro-py3
- 作为地图服务应该可以支持添加样式文件
- 发布表需要用到sde文件,使用java创建sde的代码可以看这里
- 发布表时,先在本地的空项目模板中添加数据库表作为图层,然后上传发布这个项目
2,java实现
execSync异步调用参考上一篇文章
/**
* 调用python发布sqlserver数据库表到arcgis
*
* @param sde sde文件路径 D:\\ITS\\itsPython\\192.168.10.153.sde
* @param host arcgis地址 https://aaa.myarcgis.com/arcgis
* @param name arcgis用户名 username
* @param password arcgis密码 xxxx
* @param table 表名 STB
* @param stylePath 样式文件路径 D:/ITS/temp/dbid/xxx.lyrx
* @return
* @throws Exception
*/
public String publishTableToArcgisV2(String sde, String host, String name, String password, String table, String stylePath) throws Exception {
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_CREATE_TABLE2;
params.add(pyScriptName);
params.add(sde);
params.add(host);
params.add(name);
params.add(password);
params.add(table);
params.add(stylePath);
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://aaa.myarcgis.com/arcgis", "lzwpro", "lzwpro123", "SD","D:/ITS/temp/dbid/xxx.lyrx")
int i = execSync(pyScriptName, arr);
if (i == 0) {
//https://lzw.gis107.com/server/rest/services/SD/MapServer
return getPublishTableMapUrl(host, table);
} else {
throw new Exception("执行python异常");
}
}
3,python脚本
- 发布表是在本地一个空的项目作为模板(D:\ITS\map\MyProject2),添加数据库表,生成草稿文件来发布;
- 空项目文件可以使用arcgis pro创建项目删除所有地图得到;
- 添加表图层是要根据空间表实际类型来,区分矢量表和栅格表;
- 指定发布目录是要确保目录在arcgis已创建,发布图层这里设置的覆盖且直接公开.
# -*- coding: UTF-8 -*-
import arcpy
import os
import calendar
import time
import shutil
# 覆盖
arcpy.env.overwriteOutput = True
log_file = open("D:/ITS/pythonlog.txt", "w")
sys.stdout = log_file
sys.stderr = log_file
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, sstylefile):
arcpy.env.workspace = sde
service_name = "map_" + table.split(".")[-1]
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("add layer")
for item in sde_list:
if item.split(".")[-1] == table:
aprx_map.addDataFromPath(sde + "\\" + item)
break
else:
print('ListFeatureClasses is null')
# 如果矢量图层未找到目标则遍历栅格图层
sde_list=arcpy.ListRasters()
for item in sde_list:
if item.split(".")[-1] == table:
aprx_map.addDataFromPath(sde + "\\" + item)
break
else:
print('ListRasters is null')
raise Exception(table + " table is not find")
print("add style")
listLayers = aprx_map.listLayers()
arcpy.ApplySymbologyFromLayer_management(listLayers[0], sstylefile)
aprx.save()
# Sign in to portal
print("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
print("Create FeatureSharingDraft")
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.portalFolder = "tablemap"
sd_draft.serverFolder = "tablemap"
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, "tablemap",None, True, None, True, None, None)
print("Finish Publishing")
# https://aaa.myarcgis.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], a[5])
#publish_single_table("D:\\ITS\\map\\sde\\64142f6fed18f3049248ae24.sde", "https://aaa.myarcgis.com/arcgis", "lzwpro", "lzwpro123", "STBHHX1", "D:/ITS/temp/646ad60076c43d31a8fe1f9f/dbo.STBHHX.lyrx")
3,可能会遇到的问题
如果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