Gis二次开发相关文件处理
发表于:2022-04-18 | 分类: 前端 后端
字数统计: 2.5k | 阅读时长: 13分钟 | 阅读量:

注意:首先需要进行geoserver环境搭建(需要在 tomcat 中 geoserver 包里的 web.xml 文件中进行跨域处理)及相关依赖引入

.shp 文件处理(解析文件并展示)
后端接收前端发送的 file 文件流,通过 GeoServer 发布,并返回一个 geojson 格式数据的 url

主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@PostMapping("/publishShpFile")
public Result publishShpFile(@RequestParam("file") MultipartFile shpFile) {
Result result = new Result();
try {
//获取geoServer连接对象
GeoServerRESTManager geoServerConnection = GeoServerPublishUtil.getGeoServerConnection(geoServerUser, geoServerPassword, geoServerUrl);
if (ObjectUtil.isNotEmpty(geoServerConnection)) {
String originalFilename = shpFile.getOriginalFilename();
File dest = new File(shpPath + "/" + originalFilename);
// 检测是否存在目录
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
if (dest.exists()) {
dest.delete();
}
// 保存shp文件到本地
shpFile.transferTo(dest);
// 发布shp文件
boolean publishResult = GeoServerPublishUtil.publishShp(geoServerConnection, dest.getAbsolutePath(), geoServerWorkspace);
result.setCode(publishResult ? 200 : 500);
result.setMessage(publishResult ? "上传成功" : "上传失败");
// 准备url
String shpUrl = geoServerUrl + "/" + geoServerWorkspace + "/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=" + geoServerWorkspace + ":" + originalFilename.split("\\.")[0] + "&maxFeatures=50&outputFormat=application%2Fjson";
result.setData(publishResult ? shpUrl : "");
} else {
result.setCode(500);
result.setMessage("上传失败,请检查geoServer账号密码");
}
} catch (Exception e) {
log.error("Exceptions:", e);
result.setCode(500);
result.setMessage("上传失败,服务器内部异常");
}
return result;
}

返回封装类:

Result.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

import lombok.Data;
import java.io.Serializable;

@Data
public class Result implements Serializable {

private static final long serialVersionUID = 1L;

/**
* 返回处理消息
*/
private String message = "";

/**
* 返回代码
*/
private Integer code = HttpStatus.SUCCESS;

/**
* 返回数据对象 data
*/
private Object data;

public Result() {

}

/**
* 初始化一个新创建的 Result 对象
*
* @param code 状态码
* @param msg 返回内容
*/
public Result(int code, String msg)
{
this(code,msg,null);
}

/**
* 初始化一个新创建的 Result 对象
*
* @param code 状态码
* @param msg 返回内容
* @param data 数据对象
*/
public Result(int code, String msg, Object data)
{
this.code = code;
this.message = msg;
this.data = data;
}
/**
* 返回成功消息
*
* @return 成功消息
*/
public static Result success()
{
return Result.success("成功");
}


/**
* 返回成功数据
*
* @return 成功消息
*/
public static Result success(Object data)
{
return Result.success("成功", data);
}


/**
* 返回成功消息
*
* @param msg 返回内容
* @return 成功消息
*/
public static Result success(String msg)
{
return Result.success(msg, null);
}

/**
* 返回成功消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
*/
public static Result success(String msg, Object data)
{
return new Result(HttpStatus.SUCCESS, msg, data);
}

/**
* 返回错误消息
*
* @return
*/
public static Result error()
{
return Result.error("失败");
}

/**
* 返回错误消息
* @return 警告消息
*/
public static Result error(Object data)
{
return Result.error("失败", data);
}
public static Result error(String msg)
{
return Result.error(msg, null);
}

/**
* 返回错误消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static Result error(String msg, Object data)
{
return new Result(HttpStatus.ERROR, msg, data);
}

/**
* 返回错误消息
*
* @param code 状态码
* @param msg 返回内容
* @return 警告消息
*/
public static Result error(int code, String msg)
{
return new Result(code, msg, null);
}
}

shp解析工具类:

GeoServerPublishUtil.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import cn.hutool.core.util.ObjectUtil;
import it.geosolutions.geoserver.rest.GeoServerRESTManager;
import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
import it.geosolutions.geoserver.rest.GeoServerRESTReader;
import it.geosolutions.geoserver.rest.decoder.RESTDataStore;
import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder;
import it.geosolutions.geoserver.rest.encoder.datastore.GSGeoTIFFDatastoreEncoder;
import it.geosolutions.geoserver.rest.encoder.datastore.GSShapefileDatastoreEncoder;
import it.geosolutions.geoserver.rest.encoder.feature.GSFeatureTypeEncoder;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.List;

/**
* @Classname GeoServerPublishUtil
*/
@Slf4j
public class GeoServerPublishUtil {

/**
* 获取geoserver连接对象
*
* @param username
* @param password
* @param geoserverUrl
* @return
*/
public static GeoServerRESTManager getGeoServerConnection(String username, String password, String geoserverUrl) {
try {
GeoServerRESTManager geoServerRESTManager = new GeoServerRESTManager(new URL(geoserverUrl), username, password);
return geoServerRESTManager;
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}


/**
* 发布tiff
*
* @param tiffPath
* @return
*/
public static boolean publishTiff(GeoServerRESTManager geoServerRESTManager, String tiffPath, String workSpace) {
try {
File tifFile = new File(tiffPath);
assert geoServerRESTManager != null;

//判断工作空间是否存在,不存在则创建
String storeName = tifFile.getName().split("\\.")[0];

//获取发布对象
GeoServerRESTPublisher publisher = geoServerRESTManager.getPublisher();
//创建工作空间
List<String> workspaces = geoServerRESTManager.getReader().getWorkspaceNames();
if (!workspaces.contains(workSpace)) {
publisher.createWorkspace(workSpace);
}

//获取当前要发布的数据
RESTDataStore dataStore = geoServerRESTManager.getReader().getDatastore(workSpace, storeName);
if (ObjectUtil.isEmpty(dataStore)) {
GSGeoTIFFDatastoreEncoder gsGeoTIFFDataStoreEncoders = new GSGeoTIFFDatastoreEncoder(storeName);
gsGeoTIFFDataStoreEncoders.setWorkspaceName(workSpace);
gsGeoTIFFDataStoreEncoders.setUrl(new URL("file:" + tifFile.getName()));
//创建图层
geoServerRESTManager.getStoreManager().create(workSpace, gsGeoTIFFDataStoreEncoders);
//发布图层
return geoServerRESTManager.getPublisher().publishGeoTIFF(workSpace, storeName, tifFile);
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

/**
* 发布shp文件
*
* @param geoServerRESTManager
* @param shpPath
* @param workSpace
* @return
*/
public static boolean publishShp(GeoServerRESTManager geoServerRESTManager, String shpPath, String workSpace) {
assert geoServerRESTManager != null;
File shpFile = new File(shpPath);
GeoServerRESTReader restReader = geoServerRESTManager.getReader();
GeoServerRESTPublisher restPublisher = geoServerRESTManager.getPublisher();
// 存在相应的工作区
if (!restReader.existsWorkspace(workSpace)) {
restPublisher.createWorkspace(workSpace);
}
//shp数据存储,如果存在 先删除
String dataSetName = shpFile.getName().split("\\.")[0];
if (restReader.existsDatastore(workSpace, dataSetName)) {
restPublisher.removeDatastore(workSpace, dataSetName, true);
}
//创建shape文件存储
try {
//shp文件所在的位置
String urlDataStorePath = shpFile.getPath();
// 数据存储需要的文件
String shpFilePath = String.format("file://%s", urlDataStorePath);
URL urlShapeFile = new URL(shpFilePath);
// 创建数据集
GSShapefileDatastoreEncoder dataStoreEncoder = new GSShapefileDatastoreEncoder(dataSetName, urlShapeFile);
dataStoreEncoder.setCharset(Charset.forName("GBK"));
geoServerRESTManager.getStoreManager().create(workSpace, dataStoreEncoder);
} catch (MalformedURLException e) {
e.printStackTrace();
}

//shp图层layer
String layerName = shpFile.getName().split("\\.")[0];
if (restReader.existsLayer(workSpace, layerName)) {
restPublisher.removeLayer(workSpace, layerName);
}
//发布图层
GSFeatureTypeEncoder gsFeatureTypeEncoder = new GSFeatureTypeEncoder();
gsFeatureTypeEncoder.setName(layerName);
gsFeatureTypeEncoder.setTitle(layerName);
gsFeatureTypeEncoder.setSRS(GeoServerRESTPublisher.DEFAULT_CRS);
GSLayerEncoder gsLayerEncoder = new GSLayerEncoder();
return restPublisher.publishDBLayer(workSpace, dataSetName, gsFeatureTypeEncoder, gsLayerEncoder);
}

}

此时后端返回 res.data 即为 geojson 格式的 url

geoServerUrl + "/" + geoServerWorkspace + "/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=" + geoServerWorkspace + ":" + originalFilename.split("\\.")[0] + "&maxFeatures=50&outputFormat=application%2Fjson"
👇
http://localhost:18888/geoserver/geoserver_space/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=geoserver_space:1639645666000&maxFeatures=50&outputFormat=application%2Fjson

前端使用此 url
1
2
3
4
5
6
7
8
9
10
11
this.map.addLayer({ // this.map 为地图实例
id: "shp",
type: "fill",
source: {
type: "geojson",
data: response.data, // response.data 为返回url
},
paint: {
"fill-color": "rgba(247, 79, 69, 0.5)", // 填充颜色
},
});
.tif 文件处理(解析文件并展示)
同理 后端接收前端发送的 file 文件流,通过 GeoServer 发布,并返回一个 WMS 瓦片格式数据的 url

主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
String tiffPath = decryptFilePath + partFile.getName(); // partFile 为 tif 文件
//解析tif图片获取经纬度
log.info("解析tiff获取经纬度开始");
JSONArray coordinateArray = TiffUtil.getCoordinateByTiff(tiffPath);
String bubbleLocation = coordinateArray.toString();
log.info("解析tiff获取经纬度结束");
//发布tiff文件
log.info("tiff开始发布");
GeoServerRESTManager geoServerConnection = GeoServerPublishUtil.getGeoServerConnection(geoServerUser, geoServerPassword, geoServerUrl);
boolean publishResult = GeoServerPublishUtil.publishTiff(geoServerConnection, tiffPath, geoServerWorkspace);
if (!publishResult) {
return Result.error("请上传正确的tif文件!");
}
//boolean publishResult = GeoServerLayerPublish.publishTiff(geoServerConnection,tiffPath,geoServerWorkspace);
log.info("tiff发布完成");
// 此时拿到url 主要代码片结束
String tiffPublishUrl = geoServerUrl + "/" + geoServerWorkspace + "/wms?service=WMS&version=1.1.0&request=GetMap&layers=" + geoServerWorkspace + ":" + partFile.getName().split("\\.")[0] + "&styles=&bbox={bbox-epsg-3857}&width=768&height=552&srs=EPSG:3857&format=image%2Fpng&transparent=true";
// //通过经纬度查询数据库中是否有相同位置上传
// QueryWrapper<FileTiffUploadVO> wrapper = new QueryWrapper<>();
// wrapper.lambda().eq(FileTiffUploadVO::getBubbleLocation, bubbleLocation);
// List<FileTiffUploadVO> fileTiffUploadVOS = fileTiffUploadMapper.selectList(wrapper);
// //如果存在,复用ID信息
// if (ObjectUtil.isNotEmpty(fileTiffUploadVOS) && fileTiffUploadVOS.size() > 0) {
// FileTiffUploadVO fileTiffUploadVO = fileTiffUploadVOS.get(0);
// fileTiffUploadVO.setFileName(partFile.getName());
// fileTiffUploadVO.setFileTiffPath(tiffPath);
// fileTiffUploadVO.setFilePngPath(pngFilePath);
// fileTiffUploadVO.setTiffPublishUrl(publishResult ? tiffPublishUrl : "");
// fileTiffUploadVO.setTiffPublishStatus(publishResult ? 1 : 2);
// fileTiffUploadVO.setUploadTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
// fileTiffUploadService.insert(fileTiffUploadVO);
// } else {
// //如果不存在则新建存储上传信息
// FileTiffUploadVO fileTiffUploadVO = new FileTiffUploadVO();
// fileTiffUploadVO.setFileId(UUID.randomUUID().toString().replaceAll("-", ""));
// fileTiffUploadVO.setFileName(partFile.getName());
// fileTiffUploadVO.setFileTiffPath(tiffPath);
// fileTiffUploadVO.setFilePngPath(pngFilePath);
// fileTiffUploadVO.setBubbleLocation(bubbleLocation);
// fileTiffUploadVO.setTiffPublishUrl(publishResult ? tiffPublishUrl : "");
// fileTiffUploadVO.setTiffPublishStatus(publishResult ? 1 : 2);
// fileTiffUploadVO.setUploadTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
// fileTiffUploadService.insert(fileTiffUploadVO);
// }

依赖实体类:

FileTiffUploadVO.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.context.annotation.Description;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("gis_file_tiff_upload")
@Description("tiff文件上传信息")
public class FileTiffUploadVO {

private String fileId;

/**
* 图像对比气泡所在经纬度
*/
@TableField("bubble_location")
private String bubbleLocation;

/**
* 上传tiff文件名称
*/
@TableField("file_name")
private String fileName;

/**
* tiff图片位置
*/
@TableField("file_tiff_path")
private String fileTiffPath;


/**
* tiff图片发布后的URL
*/
@TableField("tiff_publish_url")
private String tiffPublishUrl;

/**
* tiff发布状态
*/
@TableField("tiff_publish_status")
private int tiffPublishStatus;

/**
* 上传时间
*/
@TableField("upload_time")
private String uploadTime;
}

tif解析工具类:

TiffUtil.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import com.alibaba.fastjson.JSONArray;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
import static java.lang.Math.PI;
import static java.lang.Math.atan;
import static java.lang.Math.exp;

/**
* @Classname TiffUtil
*/
public class TiffUtil {

/**
* 解析tiff获取坐标
*
* @param tiffPath
* @return
*/
public static JSONArray getCoordinateByTiff(String tiffPath) {
//解析tif图片获取经纬度(假设通过解析tif图片获取到了经纬度)
gdal.AllRegister();
//读取tif文件
Dataset dataset = gdal.Open(tiffPath, gdalconstConstants.GA_ReadOnly);
//栅格矩阵的列数
int rasterXSize = dataset.getRasterXSize();
//栅格矩阵的行数
int rasterYSize = dataset.getRasterYSize();
//获取仿射矩阵信息
double[] doubles = dataset.GetGeoTransform();
//获取投影信息
double aDouble = doubles[0];
double aDouble1 = doubles[3];
double aDouble2 = doubles[1] * rasterXSize + aDouble;
double aDouble3 = doubles[5] * rasterYSize + aDouble1;
//墨卡托转WGS84:经度
double topX = mercator2Lon(aDouble);
//墨卡托转WGS84:纬度
double topY = mercator2Lat(aDouble1);
//墨卡托转WGS84:经度
double belowX = mercator2Lon(aDouble2);
//墨卡托转WGS84:纬度
double belowY = mercator2Lat(aDouble3);
//取两个坐标点,数据封装为二维数组
String coordinatesJSON = "[[" + topX + "," + topY + "]," + "[" + belowX + "," + belowY + "]]";
JSONArray jsonArray = JSONArray.parseArray(coordinatesJSON);
return jsonArray;
}

/**
* 墨卡托转WGS84:经度
*
* @param longitude
* @return
*/
private static double mercator2Lon(double longitude) {
return longitude / 20037508.34 * 180;
}

/**
* 墨卡托转WGS84:纬度
*
* @param latitude
* @return
*/
private static double mercator2Lat(double latitude) {
double latitudeTemp = latitude / 20037508.34 * 180;
return 180 / PI * (2 * atan(exp(latitudeTemp * PI / 180)) - PI / 2);
}
}

此时拿到 url 即可在前端进行处理展示

geoServerUrl + "/" + geoServerWorkspace + "/wms?service=WMS&version=1.1.0&request=GetMap&layers=" + geoServerWorkspace + ":" + partFile.getName().split("\\.")[0] + "&styles=&bbox={bbox-epsg-3857}&width=768&height=552&srs=EPSG:3857&format=image%2Fpng&transparent=true";
👇
http://localhost:18888/geoserver/a_try/wms?service=WMS&version=1.1.0&request=GetMap&layers=a_try:aaaaaaaaaaatcz&bbox={bbox-epsg-3857}&width=768&height=437&srs=EPSG:3857&format=image%2Fpng&transparent=true

前端使用此 tif url
1
2
3
4
5
6
7
8
9
10
11
12
this.map.addLayer({ // this.map 为地图实例
id: "testTif",
type: "raster", // type raster 即栅格数据
source: {
type: "raster",
tiles: [e], // e 为此前拿到的 url
tileSize: 256, // size 可随意设置 目测影响不大
},
paint: {
"raster-opacity": 1, // 透明度
},
});
至于 .dbf 文件,处理起来相对容易
1
2
3
4
5
6
7
8
9
10
11
12
13
// 文件转流
InputStream inputStream = file.getInputStream();
// 根据输入流初始化一个DBFReader实例,用来读取DBF文件信息
DBFReader reader = new DBFReader(inputStream);
// 解决乱码
reader.setCharactersetName("GBK");
// 调用DBFReader对实例方法得到path文件中字段的个数
int fieldsCount = reader.getFieldCount();
Object[] rowValues;
// 一条条取出path文件中记录
while ((rowValues = reader.nextRecord()) != null) {
rowValues.toString()
}
上一篇:
记录一下好用的Js技巧(新手向大佬勿喷)
下一篇:
Js实现网页时钟(备用)