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[i];
118                 string styleName = dataTypeConfig.StyleList[i];
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 % Xferd  Average Speed   Time    Time     Time  Current
  5                                  Dload  Upload   Total   Spent    Left  Speed
  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 { [496 bytes data]
 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 % Xferd  Average Speed   Time    Time     Time  Current
 28                                  Dload  Upload   Total   Spent    Left  Speed
 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 } [252 bytes data]
 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     0  100   252      0  16046 --:--:-- --:--:-- --:--:-- 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 % Xferd  Average Speed   Time    Time     Time  Current
 56                                  Dload  Upload   Total   Spent    Left  Speed
 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 { [52 bytes data]
 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 % Xferd  Average Speed   Time    Time     Time  Current
 80                                  Dload  Upload   Total   Spent    Left  Speed
 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 } [252 bytes data]
 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 { [9 bytes data]
101 100   261  100     9  100   252    510  14302 --:--:-- --:--:-- --:--:-- 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 % Xferd  Average Speed   Time    Time     Time  Current
108                                  Dload  Upload   Total   Spent    Left  Speed
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 } [91 bytes data]
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 { [8 bytes data]
129 100    99  100     8  100    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 % Xferd  Average Speed   Time    Time     Time  Current
135                                  Dload  Upload   Total   Spent    Left  Speed
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 } [63 bytes data]
147 100    63    0     0  100    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     0  100    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命令执行结果的判断,多个仓库的发布等等,后面再持续更新吧!

posted @ 2023-02-23 14:27  JessieR  阅读(392)  评论(0编辑  收藏  举报