我纳什神 发表于 2023-2-23 15:11:36

C# 自动化发布GeoServer之NetCDF

最近新接触了GeoServer,从零开始的研究也是折磨了好几天,发现GeoServer这块很多大佬分享各种解决方案,也是帮了我大忙,刚好告一个段落了,所以也贡献一下我这几天的研究成果,希望能帮到大家。
目标:使用GeoServer自动化发布NetCDF文件,实现部署在Linux上自动化更新图层
环境:.net6.0,GeoServer 2.21,Linux
先看一下目录结构:

 
 
 AbstracPublishHandler抽象类中写整体的处理方法,主要是对栅格文件处理的固定流程

 
附上源码:
1 using System.Runtime.InteropServices;
2
3 namespace ReservoirModelAnalysis.Module.GeoServicePublish.Common
4 {
5   /// <summary>
6   /// 发布抽象类
7   /// </summary>
8   public abstract class AbstracPublishHandler
9   {
10         /// <summary>
11         /// 测试的时候使用cmd命令,部署在linux服务器上的时候使用shell命令
12         /// </summary>
13         private Func<string, string> processCommand = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ProcessHandler.CmdProcess : ProcessHandler.ShellProcess;
14
15         /// <summary>
16         /// 数据仓库配置
17         /// </summary>
18         IDataTypeConfig dataTypeConfig;
19         /// <summary>
20         /// 发布处理
21         /// 1.先判断数据仓库是否存在,不存在直接进行第三步
22         /// 2.更新数据仓库,并且流程结束
23         /// 3.发布新的数据仓库
24         /// 4.发布指定的图层
25         /// 5.图层绑定已发布好的样式
26         /// </summary>
27         /// <param name="config">数据仓库类型配置</param>
28         /// <param name="path">文件路由</param>
29         public void Handling(IDataTypeConfig config, string path)
30         {
31             dataTypeConfig = config;
32             Console.WriteLine($"{DateTime.Now}:GeoServer发布准备开始!");
33
34             if (getCoverageStorebyName())
35             {
36               //仓库存在
37               UpdateCoverageStore(path);
38             }
39             else
40             {
41               //仓库不存在
42
43               //发布栅格存储
44               PublishCoverageStore(path);
45
46               //发布指定图层
47               PublishCoverages();
48
49               //绑定样式
50               SetLayerStyle();
51
52             }
53
54             Console.WriteLine($"{DateTime.Now}:GeoServer发布完成!");
55         }
56
57         /// <summary>
58         /// 获取指定类型的数据仓库名称
59         /// </summary>
60         /// <returns></returns>
61         private bool getCoverageStorebyName()
62         {
63             string url = $"{GeoServerConfig.GeoServerUrl}/workspaces/{dataTypeConfig.WorkSpaceName}/coveragestores/{dataTypeConfig.StoreName}.json";
64             string cmd = $"curl -v -u {GeoServerConfig.User}:{GeoServerConfig.Password} -XGET {url}";
65
66             var result = processCommand.Invoke(cmd);
67             Console.WriteLine($"判断是否有指定的数据仓库:\n【{result}】");
68
69             //简单的判断一下,内容不为nosuch的情况还有可能报其他错
70             return !(result.IndexOf("No such") > -1);
71         }
72
73         /// <summary>
74         /// 发布一个栅格数据存储
75         /// </summary>
76         /// <param name="path">栅格文件路径 使用//分割</param>
77         /// <returns></returns>
78         protected bool PublishCoverageStore(string path)
79         {
80             string xml = $"<coverageStore><name>{dataTypeConfig.StoreName}</name><type>NetCDF</type><enabled>true</enabled><workspace><name>{dataTypeConfig.WorkSpaceName}</name></workspace><__default>false</__default><url>file://{path}</url></coverageStore>";
81             string cmd = $"curl -v -u {GeoServerConfig.User}:{GeoServerConfig.Password} -XPOST -H \"Content-type: text/xml\" -d \"{xml}\" {GeoServerConfig.GeoServerUrl}/workspaces/{dataTypeConfig.WorkSpaceName}/coveragestores";
82
83             var result = processCommand.Invoke(cmd);
84
85             Console.WriteLine($"发布栅格存储结果:\n【{result}】");
86
87             return true;
88         }
89
90         /// <summary>
91         /// 发布图层
92         /// </summary>
93         /// <returns></returns>
94         protected bool PublishCoverages()
95         {
96             dataTypeConfig.LayerList.ForEach(layerName =>
97             {
98               string xml = $"<coverage><nativeCoverageName>{layerName}</nativeCoverageName><name>{layerName}</name></coverage>";
99               string url = $"{GeoServerConfig.GeoServerUrl}/workspaces/{dataTypeConfig.WorkSpaceName}/coveragestores/{dataTypeConfig.StoreName}/coverages";
100               string cmd = $"curl -v -u {GeoServerConfig.User}:{GeoServerConfig.Password} -XPOST -H \"Content-type: text/xml\" -d \"{xml}\" {url}";
101
102               var result = processCommand.Invoke(cmd);
103
104               Console.WriteLine($"发布{layerName}图层结果:\n【{result}】");
105             });
106
107             return true;
108         }
109         /// <summary>
110         /// 给图层设置样式
111         /// </summary>
112         /// <returns></returns>
113         protected bool SetLayerStyle()
114         {
115             for (int i = 0; i < dataTypeConfig.LayerList.Count; i++)
116             {
117               string layerName = dataTypeConfig.LayerList;
118               string styleName = dataTypeConfig.StyleList;
119
120               string xml = $"<layer><defaultStyle><name>{styleName}</name></defaultStyle></layer>";
121               string url = $"{GeoServerConfig.GeoServerUrl}/layers/{layerName}";
122               string cmd = $"curl -v -u {GeoServerConfig.User}:{GeoServerConfig.Password} -XPUT -H \"Content-type: text/xml\" -d \"{xml}\" {url}";
123
124               var result = processCommand.Invoke(cmd);
125
126               Console.WriteLine($"绑定{layerName}图层{styleName}样式结果:\n【{result}】");
127             }
128             return true;
129         }
130
131         /// <summary>
132         /// 更新数据仓储
133         /// </summary>
134         /// <param name="path">栅格文件路径 使用//分割</param>
135         /// <returns></returns>
136         protected bool UpdateCoverageStore(string path)
137         {
138             string xml = $"<coverageStore><name>{dataTypeConfig.StoreName}</name><type>NetCDF</type><enabled>true</enabled><workspace><name>{dataTypeConfig.WorkSpaceName}</name></workspace><__default>false</__default><url>file://{path}</url></coverageStore>";
139             string cmd = $"curl -v -u {GeoServerConfig.User}:{GeoServerConfig.Password} -XPUT -H \"Content-type: text/xml\" -d \"{xml}\" {GeoServerConfig.GeoServerUrl}/workspaces/{dataTypeConfig.WorkSpaceName}/coveragestores/{dataTypeConfig.StoreName}";
140
141             var result = processCommand.Invoke(cmd);
142
143             Console.WriteLine($"更新数据仓库{dataTypeConfig.StoreName}结果:\n【{result}】");
144
145             return true;
146         }
147   }
148 }View Code 
 DataSourceType中放具体的栅格类型处理方法,目前只用到了NetCDF,NetCDFPublishHandler继承抽象类AbstracPublishHandler直接调用Handling方法即可。
我这边是使用Job定时执行发布任务

 
 Linux上执行结果
1 2023/2/23 下午2:14:00:GeoServer发布准备开始!
2 Note: Unnecessary use of -X or --request, GET is already inferred.
3 *   Trying 192.168.1.51:8080...
4   % Total    % Received % XferdAverage Speed   Time    Time   TimeCurrent
5                                  DloadUpload   Total   Spent    LeftSpeed
6   0   0    0   0    0   0      0      0 --:--:-- --:--:-- --:--:--   0* Connected to 192.168.1.51 (192.168.1.51) port 8080 (#0)
7 * Server auth using Basic with user 'admin'
8 > GET /geoserver/rest/workspaces/workspace_demo/coveragestores/demostore.json HTTP/1.1
9 > Host: 192.168.1.51:8080
10 > Authorization: Basic YWRtaW46Z2Vvc2VydmVy
11 > User-Agent: curl/7.79.1
12 > Accept: */*
13 >
14 * Mark bundle as not supporting multiuse
15 < HTTP/1.1 200 OK
16 < X-Frame-Options: SAMEORIGIN
17 < Content-Type: application/json
18 < Transfer-Encoding: chunked
19 < Server: Jetty(9.4.44.v20210927)
20 <
21 {
22 100   491    0   491    0   0   8196      0 --:--:-- --:--:-- --:--:--8322
23 * Connection #0 to host 192.168.1.51 left intact
24 判断是否有指定的数据仓库:
25 【{"coverageStore":{"name":"demostore","type":"NetCDF","enabled":true,"workspace":{"name":"workspace_demo","href":"http://192.168.1.51:8080/geoserver/rest/workspaces/workspace_demo.json"},"_default":false,"dateCreated":"2023-02-23 05:33:01.37 UTC","dateModified":"2023-02-23 05:34:01.101 UTC","url":"file://D:\\gsFile\\HadCRUT.5.0.1.0.analysis.anomalies.ensemble_mean.nc","coverages":"http://192.168.1.51:8080/geoserver/rest/workspaces/workspace_demo/coveragestores/demostore/coverages.json"}}】
26 *   Trying 192.168.1.51:8080...
27   % Total    % Received % XferdAverage Speed   Time    Time   TimeCurrent
28                                  DloadUpload   Total   Spent    LeftSpeed
29   0   0    0   0    0   0      0      0 --:--:-- --:--:-- --:--:--   0* Connected to 192.168.1.51 (192.168.1.51) port 8080 (#0)
30 * Server auth using Basic with user 'admin'
31 > PUT /geoserver/rest/workspaces/workspace_demo/coveragestores/demostore HTTP/1.1
32 > Host: 192.168.1.51:8080
33 > Authorization: Basic YWRtaW46Z2Vvc2VydmVy
34 > User-Agent: curl/7.79.1
35 > Accept: */*
36 > Content-type: text/xml
37 > Content-Length: 252
38 >
39 }
40 * Mark bundle as not supporting multiuse
41 < HTTP/1.1 200 OK
42 < X-Frame-Options: SAMEORIGIN
43 < Content-Length: 0
44 < Server: Jetty(9.4.44.v20210927)
45 <
46 100   252    0   0100   252      016046 --:--:-- --:--:-- --:--:-- 16800
47 * Connection #0 to host 192.168.1.51 left intact
48 更新数据仓库demostore结果:
49 【】
50 2023/2/23 下午2:14:00:GeoServer发布完成!
51 2023/2/23 下午2:15:00>>>>>>执行GeoService发布
52 2023/2/23 下午2:15:00:GeoServer发布准备开始!
53 Note: Unnecessary use of -X or --request, GET is already inferred.
54 *   Trying 192.168.1.51:8080...
55   % Total    % Received % XferdAverage Speed   Time    Time   TimeCurrent
56                                  DloadUpload   Total   Spent    LeftSpeed
57   0   0    0   0    0   0      0      0 --:--:-- --:--:-- --:--:--   0* Connected to 192.168.1.51 (192.168.1.51) port 8080 (#0)
58 * Server auth using Basic with user 'admin'
59 > GET /geoserver/rest/workspaces/workspace_demo/coveragestores/demostore.json HTTP/1.1
60 > Host: 192.168.1.51:8080
61 > Authorization: Basic YWRtaW46Z2Vvc2VydmVy
62 > User-Agent: curl/7.79.1
63 > Accept: */*
64 >
65 * Mark bundle as not supporting multiuse
66 < HTTP/1.1 404 Not Found
67 < X-Frame-Options: SAMEORIGIN
68 < Content-Type: text/plain
69 < Transfer-Encoding: chunked
70 < Server: Jetty(9.4.44.v20210927)
71 <
72 {
73 100    48    0    48    0   0   6269      0 --:--:-- --:--:-- --:--:--6857
74 * Connection #0 to host 192.168.1.51 left intact
75 判断是否有指定的数据仓库:
76 【No such coverage store: workspace_demo,demostore】
77 Note: Unnecessary use of -X or --request, POST is already inferred.
78 *   Trying 192.168.1.51:8080...
79   % Total    % Received % XferdAverage Speed   Time    Time   TimeCurrent
80                                  DloadUpload   Total   Spent    LeftSpeed
81   0   0    0   0    0   0      0      0 --:--:-- --:--:-- --:--:--   0* Connected to 192.168.1.51 (192.168.1.51) port 8080 (#0)
82 * Server auth using Basic with user 'admin'
83 > POST /geoserver/rest/workspaces/workspace_demo/coveragestores HTTP/1.1
84 > Host: 192.168.1.51:8080
85 > Authorization: Basic YWRtaW46Z2Vvc2VydmVy
86 > User-Agent: curl/7.79.1
87 > Accept: */*
88 > Content-type: text/xml
89 > Content-Length: 252
90 >
91 }
92 * Mark bundle as not supporting multiuse
93 < HTTP/1.1 201 Created
94 < X-Frame-Options: SAMEORIGIN
95 < Location: http://192.168.1.51:8080/geoserver/rest/workspaces/workspace_demo/coveragestores/demostore
96 < Content-Type: text/plain
97 < Content-Length: 9
98 < Server: Jetty(9.4.44.v20210927)
99 <
100 {
101 100   261100   9100   252    51014302 --:--:-- --:--:-- --:--:-- 15352
102 * Connection #0 to host 192.168.1.51 left intact
103 发布栅格存储结果:
104 【demostore】
105 Note: Unnecessary use of -X or --request, POST is already inferred.
106 *   Trying 192.168.1.51:8080...
107   % Total    % Received % XferdAverage Speed   Time    Time   TimeCurrent
108                                  DloadUpload   Total   Spent    LeftSpeed
109   0   0    0   0    0   0      0      0 --:--:-- --:--:-- --:--:--   0* Connected to 192.168.1.51 (192.168.1.51) port 8080 (#0)
110 * Server auth using Basic with user 'admin'
111 > POST /geoserver/rest/workspaces/workspace_demo/coveragestores/demostore/coverages HTTP/1.1
112 > Host: 192.168.1.51:8080
113 > Authorization: Basic YWRtaW46Z2Vvc2VydmVy
114 > User-Agent: curl/7.79.1
115 > Accept: */*
116 > Content-type: text/xml
117 > Content-Length: 91
118 >
119 }
120 * Mark bundle as not supporting multiuse
121 < HTTP/1.1 201 Created
122 < X-Frame-Options: SAMEORIGIN
123 < Location: http://192.168.1.51:8080/geoserver/rest/workspaces/workspace_demo/coveragestores/demostore/coverages/tas_mean
124 < Content-Type: text/plain
125 < Content-Length: 8
126 < Server: Jetty(9.4.44.v20210927)
127 <
128 {
129 100    99100   8100    91   38    436 --:--:-- --:--:-- --:--:--   478
130 * Connection #0 to host 192.168.1.51 left intact
131 发布tas_mean图层结果:
132 【tas_mean】
133 *   Trying 192.168.1.51:8080...
134   % Total    % Received % XferdAverage Speed   Time    Time   TimeCurrent
135                                  DloadUpload   Total   Spent    LeftSpeed
136   0   0    0   0    0   0      0      0 --:--:-- --:--:-- --:--:--   0* Connected to 192.168.1.51 (192.168.1.51) port 8080 (#0)
137 * Server auth using Basic with user 'admin'
138 > PUT /geoserver/rest/layers/tas_mean HTTP/1.1
139 > Host: 192.168.1.51:8080
140 > Authorization: Basic YWRtaW46Z2Vvc2VydmVy
141 > User-Agent: curl/7.79.1
142 > Accept: */*
143 > Content-type: text/xml
144 > Content-Length: 63
145 >
146 }
147 100    63    0   0100    63      0   7387 --:--:-- --:--:-- --:--:--7875* Mark bundle as not supporting multiuse
148 < HTTP/1.1 200 OK
149 < X-Frame-Options: SAMEORIGIN
150 < Content-Length: 0
151 < Server: Jetty(9.4.44.v20210927)
152 <
153 100    63    0   0100    63      0   1837 --:--:-- --:--:-- --:--:--1852
154 * Connection #0 to host 192.168.1.51 left intact
155 绑定tas_mean图层raster样式结果:
156 【】
157 2023/2/23 下午2:15:00:GeoServer发布完成!Linux执行结果目前只是一个简单跑通的状态,里面其实还有许多需要完善的地方,包括对curl命令执行结果的判断,多个仓库的发布等等,后面再持续更新吧!

来源:https://www.cnblogs.com/JessieR/archive/2023/02/23/17147851.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: C# 自动化发布GeoServer之NetCDF