C# 自動化發佈GeoServer之NetCDF

来源:https://www.cnblogs.com/JessieR/archive/2023/02/23/17147851.html
-Advertisement-
Play Games

最近新接觸了GeoServer,從零開始的研究也是折磨了好幾天,發現GeoServer這塊很多大佬分享各種解決方案,也是幫了我大忙,剛好告一個段落了,所以也貢獻一下我這幾天的研究成果,希望能幫到大家。 目標:使用GeoServer自動化發佈NetCDF文件,實現部署在Linux上自動化更新圖層 環境 ...


最近新接觸了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命令執行結果的判斷,多個倉庫的發佈等等,後面再持續更新吧!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一.正常加鎖 當兩個用戶同時註冊一個用戶名時,為保證用戶名不能重覆,因此對其註冊的用戶名加鎖。 具體步驟: 獲得用戶註冊的用戶名,進行判斷,如果為空則對其進行加鎖,保存到資料庫,釋放鎖資源。 二.線程出現阻塞 當A線程加鎖後出現阻塞時,導致數據還沒有存到資料庫,鎖的時間便會失效。 B線程便會執行,對 ...
  • 睏倦的時候寫了個個獲取本地時間,列印總比當前時間大8小時,找了很久原因 package main import ( "fmt" "time" ) func main() { now := time.Now() fmt.Println(now) fmt.Println("nowStr:", now.F ...
  • pandas條件替換值(where&mask) 在日常分析中,經常會遇到對數據的篩選處理相關的工作,我們可以使用loc和iloc定位分析篩選的列或行數據,下麵介紹一種高級篩選的用法where和mask。 pd.where: 替換條件(condition)為Flase處的值 pd.mask: 替換條件 ...
  • 這篇文章主要描述分散式系統中經常討論的CAP理論,它從一致性、可用性和分區容錯性是分散式系統的三個特征,我們只能滿足其中兩個特征,對於分散式系統來說,根據不同的應用場景,可以是AP,也可以是CP。 ...
  • Java ”框架 = 註解 + 反射 + 設計模式“ 之 反射詳解 每博一文案 無論幸福還是苦難,無論光榮還是屈辱,你都要自己遭遇與承受。 —————— 《平凡的世界》 孫少平 多少美好的東西消失和毀滅了,世界還像什麼事也沒有發生,是的,生活在繼續著。 可是,生活中的每一個卻在不斷地失去自己最珍貴的 ...
  • RestSharp RestSharp是一個輕量的,不依賴任何第三方的模擬Http的組件或者類庫。RestSharp具體以下特性;支持net4.0++,支持HTTP的GET, POST, PUT, HEAD, OPTIONS, DELETE等操作,支持oAuth 1, oAuth 2, Basic, ...
  • 在使用應用程式的過程中,經常要求應用程式只能運行一次。如果發現重覆開啟,應從系統進程列表中搜索到已經開啟的進程,並將該進程視窗移到最前端顯示。 記錄一下過程。 實現過程 在 Program.cs 文件的 Program 類中聲明兩個外部調用函數 [DllImport("User32")] priva ...
  • 概述 裝飾器模式 允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作為現有的類的一個包裝。這種模式創建了一個裝飾類,用來包裝原有的類,併在保持類方法簽名完整性的前提下,提供了額外的功能。 簡單理解就是動態的給一個對象添加一些額外的職責,就增加功能來說,裝飾 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...