diff --git a/Infrastructure/Infrastructure.csproj b/Infrastructure/Infrastructure.csproj
index 0a9fd22..37b40b6 100644
--- a/Infrastructure/Infrastructure.csproj
+++ b/Infrastructure/Infrastructure.csproj
@@ -14,6 +14,8 @@
+
+
diff --git a/Infrastructure/Utils/BoundingBox.cs b/Infrastructure/Utils/BoundingBox.cs
new file mode 100644
index 0000000..92aaf6e
--- /dev/null
+++ b/Infrastructure/Utils/BoundingBox.cs
@@ -0,0 +1,27 @@
+namespace Infrastructure.Utils;
+
+public class BoundingBox
+{
+ public double MinX { get; set; }
+ public double MinY { get; set; }
+ public double MaxX { get; set; }
+ public double MaxY { get; set; }
+
+ public BoundingBox(double minX, double minY, double maxX, double maxY)
+ {
+ MinX = minX;
+ MinY = minY;
+ MaxX = maxX;
+ MaxY = maxY;
+ }
+
+ public static BoundingBox Merge(BoundingBox bbox1, BoundingBox bbox2)
+ {
+ return new BoundingBox(
+ Math.Min(bbox1.MinX, bbox2.MinX),
+ Math.Min(bbox1.MinY, bbox2.MinY),
+ Math.Max(bbox1.MaxX, bbox2.MaxX),
+ Math.Max(bbox1.MaxY, bbox2.MaxY)
+ );
+ }
+}
\ No newline at end of file
diff --git a/Infrastructure/Utils/DateTimeExtensions.cs b/Infrastructure/Utils/DateTimeExtensions.cs
new file mode 100644
index 0000000..a41b543
--- /dev/null
+++ b/Infrastructure/Utils/DateTimeExtensions.cs
@@ -0,0 +1,12 @@
+namespace Infrastructure.Utils;
+
+public static class DateTimeExtensions
+{
+ public static int GetWeekOfYear(this DateTime time)
+ {
+ // 获取当前文化的日历
+ System.Globalization.CultureInfo cultureInfo = System.Globalization.CultureInfo.CurrentCulture;
+ // 使用 CalendarWeekRule.FirstFourDayWeek 规则计算周数
+ return cultureInfo.Calendar.GetWeekOfYear(time, System.Globalization.CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
+ }
+}
\ No newline at end of file
diff --git a/Infrastructure/Utils/GeoContext.cs b/Infrastructure/Utils/GeoContext.cs
new file mode 100644
index 0000000..704316b
--- /dev/null
+++ b/Infrastructure/Utils/GeoContext.cs
@@ -0,0 +1,57 @@
+using Microsoft.Extensions.Configuration;
+
+namespace Infrastructure.Utils;
+
+public sealed class GeoContext
+{
+ public readonly string GeoserverUrl;
+ public readonly string JobwebUrl;
+ public readonly string Workspace;
+ public readonly string Username;
+ public readonly string Password;
+ public readonly string DbSchema;
+ public readonly string DbStoreName;
+
+ public readonly string TiffStoreNamePrefix;
+ public readonly string TiffDir;
+ public readonly string ConnectionString;
+
+ private static readonly Lazy Lazy = new(() => new GeoContext());
+
+ public static GeoContext Instance => Lazy.Value;
+
+ public GeoContext()
+ {
+ // 创建配置构建器
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .AddJsonFile(
+ $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"}.json",
+ optional: true)
+ .AddEnvironmentVariables();
+ // 构建配置
+ var configuration = builder.Build();
+ // 读取连接字符串
+ var connectionString = configuration.GetConnectionString("OpenAuthDBContext");
+ var geoserver = configuration["GeoServer:GeoserverUrl"];
+ var jobwebUrl = configuration["GeoServer:JobwebUrl"];
+ var workspace = configuration["Geoserver:Workspace"];
+ var username = configuration["Geoserver:Username"];
+ var password = configuration["Geoserver:Password"];
+ var dbSchema = configuration["Geoserver:DbSchema"];
+ var dbStoreName = configuration["Geoserver:DbStoreName"];
+ var tiffStoreNamePrefix = configuration["Geoserver:TiffStoreNamePrefix"];
+ var tiffDir = configuration["Geoserver:TiffDir"];
+ ConnectionString = connectionString;
+ GeoserverUrl = geoserver;
+ JobwebUrl = jobwebUrl;
+ Workspace = workspace;
+ Username = username;
+ Password = password;
+ DbSchema = dbSchema;
+ DbStoreName = dbStoreName;
+ TiffStoreNamePrefix = tiffStoreNamePrefix;
+ TiffDir = tiffDir;
+ }
+}
\ No newline at end of file
diff --git a/Infrastructure/Utils/GeoUtil.cs b/Infrastructure/Utils/GeoUtil.cs
new file mode 100644
index 0000000..fd09bff
--- /dev/null
+++ b/Infrastructure/Utils/GeoUtil.cs
@@ -0,0 +1,1152 @@
+using System.Dynamic;
+using System.Net;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Xml.Linq;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using OSGeo.GDAL;
+using OSGeo.OSR;
+
+namespace Infrastructure.Utils;
+
+public class GeoUtil
+{
+ private static GeoContext _geoContext = GeoContext.Instance;
+
+ // geosever 地址
+ public static readonly string GeoserverUrl = _geoContext.GeoserverUrl;
+
+ // 默认工作空间
+ public static readonly string Workspace = _geoContext.Workspace;
+
+ // geoserver 用户名
+ public static readonly string Username = _geoContext.Username;
+
+ // geoserver 密码
+ public static readonly string Password = _geoContext.Password;
+
+ // geosever 地址
+ public static readonly string JobwebUrl = _geoContext.JobwebUrl;
+
+ // 默认数据库 schema
+ public static readonly string DbSchema = _geoContext.DbSchema;
+ public static readonly string DbStoreName = _geoContext.DbStoreName;
+ public static readonly string ConnectionString = _geoContext.ConnectionString;
+
+ ///
+ /// 创建数据存储和图层,样式存在的话,绑定样式
+ ///
+ ///
+ ///
+ ///
+ public static async Task CreateStoreAndLayer(string workspace, string srs, string layerName, string styleName)
+ {
+ //{"PORT":"5432","Database":"drone_enforcement_linyi_20240712","HOST":"192.168.10.102","PASSWORD":"123456","USER ID":"postgres"}
+ var dbElement = ParseConnectionString(ConnectionString);
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ // 判断是否存在工作空间
+ var existWorkspaceResponse = await ExistWorkspace(workspace);
+ if (!existWorkspaceResponse.Result)
+ {
+ var createWorkspaceResponse = await CreateWorkspace(workspace);
+ if (!createWorkspaceResponse.Result)
+ {
+ throw new Exception("创建工作空间失败");
+ }
+ }
+
+ // 判断Db仓库是否存在
+ var dbStoreExUrl = GeoserverUrl + "/rest/workspaces/" + workspace + "/datastores/" + DbStoreName + ".xml";
+ var response = await client.GetAsync(dbStoreExUrl);
+ if (response.StatusCode == HttpStatusCode.NotFound)
+ {
+ // 创建数据存储
+ var contentStr = "" +
+ "" + DbStoreName + "" +
+ "PostGIS" +
+ "true" +
+ "" +
+ "" + dbElement["HOST"] + "" +
+ "" + dbElement["PORT"] + "" +
+ "" + DbSchema + "" +
+ "" + dbElement["Database"] + "" +
+ "" + dbElement["USER ID"] + "" +
+ "" + dbElement["PASSWORD"] + "" +
+ "postgis" +
+ //"" +
+ "" +
+ "";
+
+ var createDataStoreUrl = GeoserverUrl + "/rest/workspaces/" + workspace + "/datastores";
+ var content = new StringContent(contentStr, Encoding.UTF8,
+ "text/xml");
+ // 执行创建数据存储
+ var result = await client.PostAsync(createDataStoreUrl, content);
+ var resultStr = result.Content.ReadAsStringAsync();
+ // 未校验,一般失败就是已存在
+ Console.WriteLine("创建数据存储StatusCode:" + result.StatusCode);
+ Console.WriteLine("创建数据存储返回结果:" + resultStr.Result);
+ }
+
+ // 判断图层存不存在
+ var layerExUrl = GeoserverUrl + "/rest/layers/" + workspace + ":" + layerName + ".xml";
+ var layerExResult = await client.GetAsync(layerExUrl);
+ if (layerExResult.StatusCode == HttpStatusCode.OK)
+ {
+ // 图层存在时间直接更新数据表即可
+ return true;
+ /*var deleteLayerUrl = GeoserverUrl + "/rest/layers/" + Workspace + ":" + layerName;
+ var deleteLayerResult = await client.DeleteAsync(deleteLayerUrl);
+ var deleteLayerResultStr = deleteLayerResult.Content.ReadAsStringAsync();
+ Console.WriteLine("删除图层返回结果:" + deleteLayerResultStr.Result);
+ if (deleteLayerResult.StatusCode != HttpStatusCode.OK)
+ {
+ throw new Exception("图层已存在但删除失败");
+ }*/
+ // 结束
+ }
+
+ // 创建图层1
+ var createLayerUrl = GeoserverUrl + "/rest/workspaces/" + workspace + "/datastores/" + DbStoreName +
+ "/featuretypes";
+ // var createLayerUrl = GEOSERVER_URL + "/rest/workspaces/"+WORKSPACE+"layers";
+
+ var createLayerContentStr = "" +
+ "true" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" + layerName + "" +
+ "" + layerName + "" +
+ "" + srs + "" +
+ "" + layerName + "" +
+ "";
+ Console.WriteLine("创建图层参数:" + createLayerContentStr);
+ var createLayerContent = new StringContent(createLayerContentStr, Encoding.UTF8, "text/xml");
+ var createLayerResult = await client.PostAsync(createLayerUrl, createLayerContent);
+ var createLayerResultStr = createLayerResult.Content.ReadAsStringAsync();
+ Console.WriteLine("创建图层返回code:" + createLayerResult.StatusCode);
+ Console.WriteLine("创建图层返回结果:" + createLayerResultStr.Result);
+ // 发布图层
+ var publishLayerUrl = GeoserverUrl + "/rest/layers/" + workspace + ":" + layerName + "";
+ var styleXmlPart = "";
+ if (!string.IsNullOrEmpty(styleName))
+ {
+ styleXmlPart = "" +
+ "" + styleName + "" +
+ "" + workspace + "" +
+ "";
+ }
+
+ var publishContentStr =
+ "" +
+ "true" +
+ "" +
+ "" +
+ "" +
+ styleXmlPart +
+ "";
+ Console.WriteLine("发布图层参数:" + publishContentStr);
+ var publishContent = new StringContent(publishContentStr, Encoding.UTF8, "text/xml");
+ var publishLayerResult = await client.PutAsync(publishLayerUrl, publishContent);
+ Console.WriteLine("发布图层返回结果:" + publishLayerResult.Content);
+ if (publishLayerResult.StatusCode != HttpStatusCode.OK)
+ {
+ throw new Exception("发布图层失败");
+ }
+
+ return true;
+ }
+
+ ///
+ /// 判断样式是否存在
+ ///
+ ///
+ ///
+ public static async Task ExistStyle(string workspace, string styleName)
+ {
+ using var client = new HttpClient();
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ var existStyleUrl = GeoserverUrl + "/rest/workspaces/" + workspace + "/styles/" +
+ styleName + ".xml";
+
+ var response = await client.GetAsync(existStyleUrl);
+ return response.StatusCode == HttpStatusCode.OK;
+ }
+
+ ///
+ /// 创建SLD样式并发布
+ ///
+ ///
+ ///
+ public static async Task PublishSldStyle(string sldPath, string styleName)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ // 样式名称
+ var sldFileName = Path.GetFileName(sldPath);
+ //var styleName = Path.GetFileNameWithoutExtension(sldPath);
+
+ // todo 判断样式是否存在
+ // 如何存在更新样式
+ //string apiUrl = GEOSERVER_URL + "/rest/styles?format=json&namespace=default&type=style&name={styleName}";
+
+ // 发布SLD样式两步骤 curl -v -u admin:geoserver -XPOST -H "Content-type: text/xml" -d "" http://localhost:8080/geoserver/rest/styles
+ var prePublicSld = GeoserverUrl + "/rest/workspaces/" + Workspace + "/styles";
+ // ""
+ var prePublishSldXml = "";
+
+ var response = await client.PostAsync(prePublicSld,
+ new StringContent(prePublishSldXml, Encoding.UTF8, "text/xml"));
+
+ if (response.StatusCode == HttpStatusCode.Created)
+ {
+ Console.WriteLine("SLD样式预发布返回结果:" + response.Content.ReadAsStringAsync().Result);
+ // 发布SLD样式第二步
+ // curl -v -u admin:geoserver -XPUT -H "Content-type: application/vnd.ogc.sld+xml" -d @roads.sld http://localhost:8080/geoserver/rest/styles/roads_style
+ //var publishSldToWorkspaceUrl = GeoserverUrl + "/rest/workspaces/" + Workspace + "/styles?name=" + Uri.EscapeDataString(styleName);
+ var publishSldToWorkspaceUrl = GeoserverUrl + "/rest/workspaces/" + Workspace + "/styles/" + styleName;
+
+ // SLD文件内容
+ var sldContent = await File.ReadAllTextAsync(sldPath, Encoding.UTF8);
+ // 创建请求
+ var content = new StringContent(sldContent, Encoding.UTF8,
+ "application/vnd.ogc.sld+xml");
+ // 执行创建数据存储
+ response = await client.PutAsync(publishSldToWorkspaceUrl, content);
+ // 检查响应
+ Console.WriteLine(response.StatusCode);
+ Console.WriteLine("SLD样式发布返回结果:" + response.Content.ReadAsStringAsync().Result);
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ Console.WriteLine("SLD发布成功");
+ return true;
+ }
+ }
+ else
+ {
+ Console.WriteLine("SLD图层已存在");
+ return false;
+ }
+
+ Console.WriteLine($"SLD发布失败,状态码:{response.StatusCode}");
+ return false;
+ }
+
+ // # 创建工作区(如果不存在)
+ //curl -u $USERNAME:$PASSWORD -X POST -H "Content-type: text/xml" -d "$WORKSPACE" $GEOSERVER_URL/rest/workspaces
+ ///
+ /// 解析数据库连接字符串
+ ///
+ ///
+ ///
+ static Dictionary ParseConnectionString(string connectionString)
+ {
+ var details = new Dictionary();
+ var parts = connectionString.Split(';');
+
+ foreach (var part in parts)
+ {
+ var index = part.IndexOf('=');
+ if (index != -1)
+ {
+ var key = part.Substring(0, index);
+ var value = part.Substring(index + 1);
+ details[key] = value;
+ }
+ }
+
+ return details;
+ }
+
+ ///
+ /// 获取图层bbox
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task> GetDBLayerBBox(string workspace, string storeName, string layerName)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var dbStoreExUrl =
+ $"{GeoserverUrl}/rest/workspaces/{workspace}/datastores/{storeName}/featuretypes/{layerName}.json";
+ var dbStoreExResult = await client.GetAsync(dbStoreExUrl);
+ var resultObj = JsonConvert.DeserializeObject(dbStoreExResult.Content.ReadAsStringAsync().Result);
+ if (dbStoreExResult.StatusCode == HttpStatusCode.OK)
+ {
+ var bbox = resultObj["featureType"]["latLonBoundingBox"];
+ var minx = bbox["minx"];
+ var miny = bbox["miny"];
+ var maxx = bbox["maxx"];
+ var maxy = bbox["maxy"];
+ Console.WriteLine("minx:" + minx);
+ Console.WriteLine("miny:" + miny);
+ Console.WriteLine("maxx:" + maxx);
+ Console.WriteLine("maxy:" + maxy);
+ Console.WriteLine("信息:" + dbStoreExResult.Content.ReadAsStringAsync().Result);
+ return new Response
+ {
+ Result = minx + "," + miny + "," + maxx + "," + maxy,
+ Code = 200
+ };
+ }
+
+ return new Response
+ {
+ Code = 500
+ };
+ }
+
+ ///
+ /// 取得bbox 及 srs 信息
+ ///
+ /// 工作空间名称
+ /// 存储仓库名称
+ /// 图层名称
+ ///
+ public static async Task> GetTiffLayerInfo(string workspace, string storeName, string layerName)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var dbStoreExUrl =
+ $"{GeoserverUrl}/rest/workspaces/{workspace}/coveragestores/{storeName}/coverages/{layerName}.json";
+ var dbStoreExResult = await client.GetAsync(dbStoreExUrl);
+ if (dbStoreExResult.StatusCode == HttpStatusCode.OK)
+ {
+ var resultObj = JsonConvert.DeserializeObject(dbStoreExResult.Content.ReadAsStringAsync().Result);
+ Console.WriteLine("GetTiffLayerInfo信息:" + dbStoreExResult.Content.ReadAsStringAsync().Result);
+ var bbox = resultObj["coverage"]?["nativeBoundingBox"];
+ var srs = resultObj["coverage"]?["srs"];
+ var minx = bbox["minx"];
+ var miny = bbox["miny"];
+ var maxx = bbox["maxx"];
+ var maxy = bbox["maxy"];
+ Console.WriteLine("minx:" + minx);
+ Console.WriteLine("miny:" + miny);
+ Console.WriteLine("maxx:" + maxx);
+ Console.WriteLine("maxy:" + maxy);
+ return new Response
+ {
+ Result = new { bbox = minx + "," + miny + "," + maxx + "," + maxy, srs = srs },
+ Code = 200
+ };
+ }
+
+ return new Response
+ {
+ Code = 500,
+ Message = dbStoreExResult.Content.ReadAsStringAsync().Result
+ };
+ }
+
+ ///
+ /// 删除栅格仓库
+ ///
+ ///
+ ///
+ /// 递归删除(true 仓库下所有资源都将被删除)
+ ///
+ public static async Task> DeleteCoveragesStore(string workspace, string storeName,
+ bool recurse = false)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ // 删除 coverageStore
+ // The recurse controls recursive deletion. When set to true all resources contained in the store are also removed. The default value is "false".
+ var deleteTiffStoreUrl = $"{GeoserverUrl}/rest/workspaces/{workspace}/coveragestores/{storeName}";
+ if (recurse)
+ {
+ deleteTiffStoreUrl += "?recurse=true";
+ }
+ else
+ {
+ deleteTiffStoreUrl += "?recurse=false";
+ }
+
+ var deleteTiffStoreResult = await client.DeleteAsync(deleteTiffStoreUrl);
+ Console.WriteLine("删除栅格仓库");
+ Console.WriteLine(deleteTiffStoreResult.Content.ReadAsStringAsync().Result);
+ Console.WriteLine(deleteTiffStoreResult.StatusCode);
+ switch (deleteTiffStoreResult.StatusCode)
+ {
+ case HttpStatusCode.OK:
+ return new Response
+ {
+ Result = true,
+ Code = 200
+ };
+ case HttpStatusCode.NotFound:
+ return new Response
+ {
+ Result = false,
+ Code = 404
+ };
+ default:
+ return new Response
+ {
+ Result = false,
+ Code = 500,
+ Message = deleteTiffStoreResult.Content.ReadAsStringAsync().Result
+ };
+ }
+ }
+
+ ///
+ /// 删除图层
+ ///
+ /// 工作空间,可不填
+ ///
+ ///
+ public static async Task> DeleteLayer(string workspace, string layerName)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var deleteLayerUrl = $"{GeoserverUrl}/rest/layers/{workspace}:{layerName}";
+ var deleteLayerResponse = await client.DeleteAsync(deleteLayerUrl);
+ Console.WriteLine("删除图层返回结果:");
+ Console.WriteLine(deleteLayerResponse.Content.ReadAsStringAsync().Result);
+ Console.WriteLine(deleteLayerResponse.StatusCode);
+ if (deleteLayerResponse.StatusCode == HttpStatusCode.OK)
+ {
+ return new Response
+ {
+ Result = true,
+ Code = 200
+ };
+ }
+
+ return new Response
+ {
+ Result = false,
+ Code = 500
+ };
+ }
+
+ ///
+ /// 发布GeoTiff
+ ///
+ ///
+ /// tif文件全路径
+ /// 栅格仓库名称
+ /// 图层名称
+ ///
+ public static async Task> PublishExternalGeoTIFF(string workspace, string tifFullName,
+ string storeName, string layerName)
+ {
+ var srs = "4548";
+ var tifCrs = GetTifCrs(tifFullName);
+ if (tifCrs.srs != null)
+ {
+ srs = tifCrs.srs;
+ }
+
+ if (string.IsNullOrEmpty(tifFullName) || string.IsNullOrEmpty(storeName) || string.IsNullOrEmpty(layerName))
+ {
+ return new Response
+ {
+ Result = false,
+ Message = "参数不能为空"
+ };
+ }
+
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var existWorkspaceResponse = await ExistWorkspace(workspace);
+ if (!existWorkspaceResponse.Result)
+ {
+ var createWorkspaceResponse = await CreateWorkspace(workspace);
+ if (!createWorkspaceResponse.Result)
+ {
+ throw new Exception("创建工作空间失败,请检查geoserver状态");
+ }
+ }
+
+ // 创建 coverageStore
+ var createTiffStoreUrl = $"{GeoserverUrl}/rest/workspaces/{workspace}/coveragestores";
+ var tiffXml = $"" +
+ $"{storeName}{workspace}" +
+ "true" +
+ "GeoTIFF" +
+ $"file://{tifFullName}" +
+ "";
+ //Console.WriteLine("栅格仓库xml: " + tiffXml);
+ //GeoUtil.DeleteCoveragesStore(workspace, storeName, false);
+ var content = new StringContent(tiffXml, Encoding.UTF8, "application/xml");
+ var response = await client.PostAsync(createTiffStoreUrl, content);
+ if (response.StatusCode != HttpStatusCode.Created)
+ {
+ var msg = await response.Content.ReadAsStringAsync();
+ Console.Write("创建栅格仓库code: " + response.StatusCode + "错误信息:" + msg);
+ return new Response
+ {
+ Result = false,
+ Message = "创建仓库失败:" + msg
+ };
+ }
+
+ // 创建coverages
+ var createTiffCoveragesUrl = $"{GeoserverUrl}/rest/workspaces/{workspace}/coveragestores/{storeName}/coverages";
+
+ var tiffFileName = Path.GetFileNameWithoutExtension(tifFullName);
+ // nativeName 参数必须是tiff文件名称
+ var createTiffCoveragesXml = @$"
+ {storeName}
+ {tiffFileName}
+ true
+
+
+
+ {layerName}
+ {layerName}
+ EPSG:{srs}REPROJECT_TO_DECLARED
+
+
+ InputTransparentColor
+ #000000
+
+
+ ";
+ var createTiffCoveragesContent =
+ new StringContent(createTiffCoveragesXml, Encoding.UTF8, "text/xml");
+ var createTiffCoveragesResponse = await client.PostAsync(createTiffCoveragesUrl, createTiffCoveragesContent);
+ if (createTiffCoveragesResponse.StatusCode != HttpStatusCode.Created)
+ {
+ var msg = await createTiffCoveragesResponse.Content.ReadAsStringAsync();
+ //Console.Write(createTiffCoveragesResponse.StatusCode + " ");
+ //Console.WriteLine(msg);
+ return new Response
+ {
+ Result = false,
+ Message = "创建仓库失败:" + msg
+ };
+ }
+
+ var publishTiffLayerUrl =
+ $"{GeoserverUrl}/rest/layers/{workspace}:{layerName}";
+ var publishTiffLayerXml = "true";
+ var publishTiffLayerContent = new StringContent(publishTiffLayerXml, Encoding.UTF8, "text/xml");
+ var publishTiffLayerResponse = await client.PutAsync(publishTiffLayerUrl, publishTiffLayerContent);
+ if (publishTiffLayerResponse.StatusCode != HttpStatusCode.OK)
+ {
+ var msg = await publishTiffLayerResponse.Content.ReadAsStringAsync();
+ //Console.Write(publishTiffLayerResponse.StatusCode + " ");
+ //Console.WriteLine(msg);
+ return new Response
+ {
+ Result = false,
+ Message = "发布图层失败:" + msg
+ };
+ }
+
+ return new Response
+ {
+ Result = true
+ };
+ }
+
+ ///
+ /// 判断工作空间是否存在
+ ///
+ ///
+ ///
+ public static async Task> ExistWorkspace(string workspace)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ var url = $"{GeoserverUrl}/rest/workspaces/{workspace}.xml";
+ var response = await client.GetAsync(url);
+ Console.WriteLine($"状态码:{response.StatusCode} 返回结果:{response.Content.ReadAsStringAsync().Result}");
+ if (response.StatusCode == HttpStatusCode.NotFound)
+ {
+ return new Response
+ {
+ Result = false
+ };
+ }
+
+ return new Response
+ {
+ Result = true
+ };
+ }
+
+ ///
+ /// 创建工作空间
+ ///
+ ///
+ ///
+ public static async Task> CreateWorkspace(string workspace)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ var createWorkspaceUrl = $"{GeoserverUrl}/rest/workspaces";
+ var createWorkspaceXml = $"{workspace}";
+ var createWorkspaceContent = new StringContent(createWorkspaceXml, Encoding.UTF8, "text/xml");
+ var createWorkspaceResponse = await client.PostAsync(createWorkspaceUrl, createWorkspaceContent);
+ if (createWorkspaceResponse.StatusCode == HttpStatusCode.Created)
+ {
+ return new Response
+ {
+ Result = true
+ };
+ }
+
+ return new Response
+ {
+ Result = false
+ };
+ }
+
+
+ ///
+ /// 删除工作空间
+ ///
+ ///
+ ///
+ public static async Task> DeleteWorkspace(string workspace)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ var deleteWorkspaceUrl = $"{GeoserverUrl}/rest/workspaces/{workspace}" + "?recurse=true";
+ var deleteWorkspaceResponse = await client.DeleteAsync(deleteWorkspaceUrl);
+ Console.WriteLine("删除工作空间返回结果:");
+ Console.WriteLine(deleteWorkspaceResponse.Content.ReadAsStringAsync().Result);
+ Console.WriteLine(deleteWorkspaceResponse.StatusCode);
+ if (deleteWorkspaceResponse.StatusCode == HttpStatusCode.OK)
+ {
+ return new Response
+ {
+ Result = true,
+ Code = 200
+ };
+ }
+
+ return new Response
+ {
+ Result = false,
+ Code = 500
+ };
+ }
+
+
+ public static async Task> SettingLayerReturnFormat(string workspace, string layerName)
+ {
+ using var client = new HttpClient();
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+
+ var queryLayerUrl = GeoserverUrl + "/gwc/rest/layers/" + workspace + ":" + layerName + ".xml";
+ var queryResult = await client.GetAsync(queryLayerUrl);
+ Console.WriteLine(
+ $" 结果:{queryResult.Content.ReadAsStringAsync().Result} code: {queryResult.StatusCode}");
+ if (queryResult.StatusCode == HttpStatusCode.OK)
+ {
+ var split = queryResult.Content.ReadAsStringAsync().Result.Split("");
+ var xml = split[0] + "" +
+ "application/json;type=geojson" +
+ "application/json;type=topojson" +
+ "application/vnd.mapbox-vector-tile" +
+ "application/json;type=utfgrid" +
+ split[1];
+ var setGwc = GeoserverUrl + "/gwc/rest/layers/" + workspace + ":" + layerName;
+ var content = new StringContent(xml, Encoding.UTF8,
+ "application/xml");
+ var result = await client.PostAsync(setGwc, content);
+ if (result.StatusCode == HttpStatusCode.OK)
+ {
+ return new Response()
+ {
+ Result = true,
+ Code = 200
+ };
+ }
+ }
+
+ return new Response
+ {
+ Result = false,
+ Code = 500
+ };
+ }
+
+ ///
+ /// 更新样式名,更新样式
+ ///
+ ///
+ ///
+ ///
+ public static async Task UpdateSldStyle(string sldPath, string styleName)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ var publishSldToWorkspaceUrl = GeoserverUrl + "/rest/workspaces/" + Workspace + "/styles/" + styleName;
+ // SLD文件内容
+ var sldContent = await File.ReadAllTextAsync(sldPath, Encoding.UTF8);
+ // 创建请求
+ var content = new StringContent(sldContent, Encoding.UTF8,
+ "application/vnd.ogc.sld+xml");
+ // 执行创建数据存储
+ var response = await client.PutAsync(publishSldToWorkspaceUrl, content);
+ // 检查响应
+ Console.WriteLine(response.StatusCode);
+ Console.WriteLine("SLD样式发布返回结果:" + response.Content.ReadAsStringAsync().Result);
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ Console.WriteLine("SLD发布成功");
+ return true;
+ }
+
+ return false;
+ }
+
+ public static async Task> UpdateStyle(string workspace, string layerName, string styleName)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var url = $"{GeoserverUrl}/rest/layers/{workspace}:{layerName}.xml";
+ //var xml = $"{styleName}";
+ var xml = $@"
+
+
+ {styleName}
+
+ ";
+ var content = new StringContent(xml, Encoding.UTF8,
+ "application/xml");
+ var result = await client.PutAsync(url, content);
+ if (result.StatusCode == HttpStatusCode.OK)
+ {
+ return new Response
+ {
+ Result = true,
+ };
+ }
+
+ return new Response
+ {
+ Result = false,
+ Code = 500
+ };
+ }
+
+ public static async Task> publishLayerGroup(string workspace, string layers, string layerGroupName)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var url = $"{GeoserverUrl}/rest/workspaces/{workspace}/layergroups";
+ var xml = "" +
+ "" +
+ " " + layerGroupName + "" +
+ " " + layerGroupName + "" +
+ " " +
+ " " + workspace + "" +
+ " " +
+ " " +
+ layers +
+ " " +
+ "";
+ var content = new StringContent(xml, Encoding.UTF8,
+ "text/xml");
+ var result = await client.PostAsync(url, content);
+ if (result.StatusCode == HttpStatusCode.OK)
+ {
+ return new Response
+ {
+ Result = true,
+ };
+ }
+
+ return new Response
+ {
+ Result = false,
+ Code = 500
+ };
+ }
+
+ ///
+ /// 发布GeoTiff
+ ///
+ ///
+ /// tif文件全路径
+ /// 栅格仓库名称
+ /// 图层名称
+ ///
+ public static async Task> PublishSingleGeoTIFF(string workspace, string tifFullName,
+ string storeName, string layerName)
+ {
+ if (string.IsNullOrEmpty(tifFullName) || string.IsNullOrEmpty(storeName) || string.IsNullOrEmpty(layerName))
+ {
+ return new Response
+ {
+ Result = false,
+ Message = "参数不能为空"
+ };
+ }
+
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var existWorkspaceResponse = await ExistWorkspace(workspace);
+ if (!existWorkspaceResponse.Result)
+ {
+ var createWorkspaceResponse = await CreateWorkspace(workspace);
+ if (!createWorkspaceResponse.Result)
+ {
+ throw new Exception("创建工作空间失败,请检查geoserver状态");
+ }
+ }
+
+ // 创建 coverageStore
+ var createTiffStoreUrl = $"{GeoserverUrl}/rest/workspaces/{workspace}/coveragestores";
+ var tiffXml = $"" +
+ $"{storeName}{workspace}" +
+ "true" +
+ "GeoTIFF" +
+ $"file://{tifFullName}" +
+ "";
+ //Console.WriteLine("栅格仓库xml: " + tiffXml);
+ //GeoUtil.DeleteCoveragesStore(workspace, storeName, false);
+ var content = new StringContent(tiffXml, Encoding.UTF8, "application/xml");
+ var response = await client.PostAsync(createTiffStoreUrl, content);
+ if (response.StatusCode != HttpStatusCode.Created)
+ {
+ var msg = await response.Content.ReadAsStringAsync();
+ Console.Write("创建栅格仓库code: " + response.StatusCode + "错误信息:" + msg);
+ return new Response
+ {
+ Result = false,
+ Message = "创建仓库失败:" + msg
+ };
+ }
+
+ // 创建coverages
+ var createTiffCoveragesUrl = $"{GeoserverUrl}/rest/workspaces/{workspace}/coveragestores/{storeName}/coverages";
+
+ var tiffFileName = Path.GetFileName(tifFullName).Replace(Path.GetExtension(tifFullName), "");
+ // nativeName 参数必须是tiff文件名称
+ var createTiffCoveragesXml = @$"
+
+ true
+
+
+
+ {layerName}
+ {layerName}
+ EPSG:4548REPROJECT_TO_DECLARED
+
+ ";
+ var createTiffCoveragesContent =
+ new StringContent(createTiffCoveragesXml, Encoding.UTF8, "text/xml");
+ var createTiffCoveragesResponse = await client.PostAsync(createTiffCoveragesUrl, createTiffCoveragesContent);
+ if (createTiffCoveragesResponse.StatusCode != HttpStatusCode.Created)
+ {
+ var msg = await createTiffCoveragesResponse.Content.ReadAsStringAsync();
+ Console.Write(createTiffCoveragesResponse.StatusCode + " ");
+ Console.WriteLine(msg);
+ return new Response
+ {
+ Result = false,
+ Message = "创建仓库失败:" + msg
+ };
+ }
+
+ var publishTiffLayerUrl =
+ $"{GeoserverUrl}/rest/layers/{workspace}:{layerName}";
+ var publishTiffLayerXml = "true";
+ var publishTiffLayerContent = new StringContent(publishTiffLayerXml, Encoding.UTF8, "text/xml");
+ var publishTiffLayerResponse = await client.PutAsync(publishTiffLayerUrl, publishTiffLayerContent);
+ if (publishTiffLayerResponse.StatusCode != HttpStatusCode.OK)
+ {
+ var msg = await publishTiffLayerResponse.Content.ReadAsStringAsync();
+ Console.Write(publishTiffLayerResponse.StatusCode + " ");
+ Console.WriteLine(msg);
+ return new Response
+ {
+ Result = false,
+ Message = "发布图层失败:" + msg
+ };
+ }
+
+ return new Response
+ {
+ Result = true
+ };
+ }
+
+ public static async Task GetTiffLayerInfo1(string workspace, string storeName, string layerName)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace;
+ }
+
+ var dbStoreExUrl =
+ $"{GeoserverUrl}/rest/workspaces/{workspace}/coveragestores/{storeName}/coverages/{layerName}.json";
+ var dbStoreExResult = await client.GetAsync(dbStoreExUrl);
+ if (dbStoreExResult.StatusCode == HttpStatusCode.OK)
+ {
+ var resultObj = JsonConvert.DeserializeObject(dbStoreExResult.Content.ReadAsStringAsync().Result);
+ return JsonConvert.SerializeObject(resultObj);
+ }
+
+ return "执行失败";
+ }
+
+ ///
+ /// 查询图层组是否存在
+ ///
+ /// 工作空间名称
+ /// 图层组名称
+ /// 图层组是否存在
+ public static async Task ExistLayerGroup(string workspace, string layerGroupName)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace; // 如果没有指定工作空间,默认使用 "default"
+ }
+
+ var existLayerGroupUrl = $"{GeoserverUrl}/rest/workspaces/{workspace}/layergroups/{layerGroupName}.json";
+
+ var response = await client.GetAsync(existLayerGroupUrl);
+ return response.StatusCode == HttpStatusCode.OK;
+ }
+
+ ///
+ /// 向图层组中添加图层
+ ///
+ /// 工作空间名称
+ /// 图层组名称
+ /// 要添加的图层名称列表
+ /// 操作是否成功
+ public static async Task AddLayersToLayerGroup(string workspace, string layerGroupName,
+ List layerNames)
+ {
+ using var client = new HttpClient();
+ var usernamePassword = Username + ":" + Password;
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Basic",
+ Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
+
+ if (string.IsNullOrEmpty(workspace))
+ {
+ workspace = Workspace; // 如果没有指定工作空间
+ }
+
+ var addLayersUrl = $"{GeoserverUrl}/rest/workspaces/{workspace}/layergroups/{layerGroupName}.xml";
+ var groupResponse = client.GetAsync(addLayersUrl).Result.Content.ReadAsStringAsync();
+ var existingLayers = XDocument.Parse(groupResponse.Result).Descendants("publishables").Descendants("published")
+ .Descendants("name").Select(l => l.Value).ToList();
+ var layersXml = string.Join("",
+ layerNames.Select(layerName => $"{workspace}:{layerName}")
+ .Union(existingLayers.Select(x => $"{x}")).Distinct());
+ layerNames.AddRange(existingLayers);
+ var stylesXml = string.Join("", layerNames.Select(layerName => ""));
+ const string fixedBbox =
+ "117.34046403513817,34.331716698906675,119.27763051149853,36.263686454243626";
+ var requestBody = $@"
+
+ {layerGroupName}
+
+ {workspace}
+
+ {layerGroupName}
+
+ {layersXml}
+
+
+ {fixedBbox.Split(',')[0]}
+ {fixedBbox.Split(',')[1]}
+ {fixedBbox.Split(',')[2]}
+ {fixedBbox.Split(',')[3]}
+ EPSG:4326
+
+
+ {stylesXml}
+
+ ";
+ var content = new StringContent(requestBody, Encoding.UTF8, "text/xml");
+ // 发送 PUT 请求
+ var response = await client.PutAsync(addLayersUrl, content);
+ // 检查响应状态码
+ return response.IsSuccessStatusCode;
+ }
+
+ public static dynamic GetTifCrs(string filePath)
+ {
+ GdalConfiguration.ConfigureGdal();
+ GdalConfiguration.ConfigureOgr(); //矢量
+ GdalConfiguration.ConfigureOgr();
+ // 初始化 GDAL
+ Gdal.AllRegister();
+
+ // 打开 TIFF 文件
+ //string filePath = "C:/ChengGuoFinal/tiff/无人机巡飞影像数据/20240713/兰山区/20240713兰山区马厂湖_0.2.tif.aux_更新.tif";
+ Dataset dataset = Gdal.Open(filePath, Access.GA_ReadOnly);
+
+ if (dataset == null)
+ {
+ Console.WriteLine("无法打开 TIFF 文件");
+ throw new Exception("无法打开 TIFF 文件");
+ }
+
+ // 获取投影信息
+ string projection = dataset.GetProjection();
+ var x = dataset.GetProjectionRef();
+ if (!string.IsNullOrEmpty(projection))
+ {
+ Console.WriteLine("投影信息:");
+ Console.WriteLine(projection);
+ }
+ else
+ {
+ Console.WriteLine("无法获取投影信息");
+ }
+
+ // 获取空间参照信息
+ SpatialReference srs = dataset.GetSpatialRef();
+ Console.WriteLine("空间参照信息:");
+ // 解析EPSG代码
+ // 如果没有EPSG代码,可以尝试其他方法获取
+ var epsgCode = srs.GetAuthorityCode(null);
+ Console.WriteLine($"EPSG代码: {epsgCode}");
+ // 关闭数据集
+ dataset.Dispose();
+ dynamic obj = new ExpandoObject();
+ obj.projection = projection;
+ obj.srs = epsgCode;
+ return obj;
+ }
+}
\ No newline at end of file
diff --git a/Infrastructure/Utils/ShapeUtil.cs b/Infrastructure/Utils/ShapeUtil.cs
new file mode 100644
index 0000000..906e0fc
--- /dev/null
+++ b/Infrastructure/Utils/ShapeUtil.cs
@@ -0,0 +1,160 @@
+using System.IO.Compression;
+using System.Text;
+using NetTopologySuite.Geometries;
+using NetTopologySuite.IO;
+
+namespace Infrastructure.Utils;
+
+public class ShapeUtil
+{
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List> getRows(string shpPath)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// 支持
+ ///
+ ///
+ ///
+ public static List> ReadAllGeometry(string shpPath)
+ {
+ // 取得后缀,如果是zip,则解压
+ var fileExtension = Path.GetExtension(shpPath);
+ if (!fileExtension.Equals(".shp") && !fileExtension.Equals(".zip"))
+ {
+ throw new Exception("不支持的文件格式");
+ }
+
+ // 设置字符编码
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+ var gbk = Encoding.GetEncoding("gbk");
+ if (fileExtension == ".zip")
+ {
+ var extractPath = Path.GetDirectoryName(shpPath) + "\\temp";
+ Directory.CreateDirectory(extractPath);
+
+ using (var archive = ZipFile.OpenRead(shpPath))
+ {
+ // 列举ZIP文件中的条目
+ foreach (var entry in archive.Entries)
+ {
+ Console.WriteLine("zip 包含文件:");
+ var fileName = gbk.GetString(Encoding.Default.GetBytes(entry.FullName));
+ Console.WriteLine(fileName);
+ }
+
+ // 提取ZIP文件中的所有文件到指定目录
+
+ foreach (var entry in archive.Entries)
+ {
+ if (entry.Name != string.Empty)
+ {
+ // 确保完整路径存在 entry.FullName 是否可以编码
+ var fixedEntryName = entry.FullName.Replace("/", "");
+ var destinationPath = Path.GetFullPath(Path.Combine(extractPath, fixedEntryName));
+ Console.WriteLine("解压文件路径:" + destinationPath);
+ if (!destinationPath.StartsWith(Path.GetFullPath(extractPath) + Path.DirectorySeparatorChar))
+ {
+ throw new UnauthorizedAccessException("试图提取的文件超出了目标文件夹的路径边界。");
+ }
+
+ // 提取条目到目标路径
+ entry.ExtractToFile(destinationPath, overwrite: true);
+ }
+ }
+ }
+
+ // 遍历解压目录,是否有shp后缀的文件
+ if (!Directory.Exists(extractPath))
+ {
+ throw new Exception("文件解压失败");
+ }
+
+ // 查找
+ var dirInfo = new DirectoryInfo(extractPath);
+ // zip 压缩包中只有一个shp文件
+ shpPath = dirInfo.GetFiles("*.shp", SearchOption.AllDirectories)[0].FullName;
+ }
+
+ var data = ParseShape(shpPath, null);
+ var tifPath = data.First()["Image"].ToString();
+ if (CheckForGarbledText(tifPath))
+ {
+ // 乱码,需要解码
+ data = ParseShape(shpPath, gbk);
+ }
+
+ return data;
+ }
+
+ private static List> ParseShape(string shpPath, Encoding code)
+ {
+ using var dataReader = code == null
+ ? new ShapefileDataReader(shpPath, GeometryFactory.Default)
+ : new ShapefileDataReader(shpPath, GeometryFactory.Default, code);
+ Console.WriteLine("记录数" + dataReader.RecordCount);
+ List> rows = new List>();
+ while (dataReader.Read())
+ {
+ Dictionary row = new Dictionary();
+ // 读取列
+ for (int i = 0, j = 0; i < dataReader.FieldCount; i++)
+ {
+ var colName = dataReader.GetName(i);
+ var value = dataReader.GetValue(i);
+ row.Add(colName, value);
+ }
+
+ rows.Add(row);
+ }
+
+ return rows;
+ // return NetTopologySuite.IO.Esri.Shapefile.ReadAllGeometries(shpPath);
+ }
+
+ ///
+ /// 判断是否乱码
+ ///
+ ///
+ ///
+ private static bool CheckForGarbledText(string content)
+ {
+ try
+ {
+ // 检查是否有不可打印的字符
+ foreach (char c in content)
+ {
+ if (char.IsControl(c) && !char.IsWhiteSpace(c))
+ {
+ return true; // 发现不可打印的控制字符
+ }
+ }
+ // 检查是否有不常见的字符
+ foreach (char c in content)
+ {
+ if (c > 0x7F && !char.IsLetterOrDigit(c) && !char.IsPunctuation(c) && !char.IsSymbol(c) &&
+ !char.IsWhiteSpace(c))
+ {
+ return true; // 发现不常见的字符
+ }
+ }
+
+ return false; // 没有发现乱码
+ }
+ catch (DecoderFallbackException)
+ {
+ return true; // 解码失败,存在乱码
+ }
+ catch (Exception ex)
+ {
+ return true; // 其他异常,可能表示存在乱码
+ }
+ }
+}
\ No newline at end of file