需求描述
要求上传一个shp文件能够读取其中的空间矢量字段。
简单分析
- SHP上传格式应该有两种(zip格式和
.shp
的格式 - 文件内部可能存在多个空间矢量,结果以列表形式返回
- 文件不大,使用MultipartFile上传上传即可
- 结合geo-tools读取空间字段,并转换为WKT格式(由于geo-tools版本较多,同一个方法在不同的版本下不一定可行,这里使用的geotools版本是
25-SNAPSHOT
代码
先上可行代码
@Value("${huicoo.temp_path}")
private String FILE_UPLOAD_DIR;
@Override
public RestResult transShpToWkt(MultipartFile file) throws IOException {
// 先获取文件类型,判断是否符合预期
String fileType = Objects.requireNonNull(file.getOriginalFilename(), "文件名不能为空")
.substring(file.getOriginalFilename().lastIndexOf(".") + 1);
if (!"shp".equals(fileType)){
ExceptionFactory.throwException(ResultCode.PARAM_ERROR , "文件类型错误");
}
File shapeFile = new File(FILE_UPLOAD_DIR+"/temp.shp");
if (shapeFile.exists()) {
shapeFile.delete();
log.error("文件残留,已删除");
}
// file.transferTo(shapeFile.getAbsoluteFile());
log.info("开始拷贝文件 {} ————> {}" , file.getName() , shapeFile.getAbsolutePath());
FileUtils.copyInputStreamToFile(file.getInputStream() , shapeFile);
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
ShapefileDataStore dataStore = (ShapefileDataStore) dataStoreFactory.createDataStore(shapeFile.toURI().toURL());
dataStore.setCharset(Charset.forName("UTF-8"));
SimpleFeatureSource featureSource = dataStore.getFeatureSource();
SimpleFeatureIterator featureIterator = featureSource.getFeatures().features();
List<String> wktList = new ArrayList<>();
while (featureIterator.hasNext()) {
SimpleFeature feature = featureIterator.next();
Collection<Property> properties = feature.getProperties();
//遍历feature的properties
for (Property property : properties) {
String value = "";
if (null != property.getValue()) {
value = property.getValue().toString();
}
if (StringUtils.hasText(value)){
wktList.add(value);
}
}
}
featureIterator.close();
dataStore.dispose();
if (shapeFile.exists()) {
shapeFile.delete();
log.error("文件残留,已删除");
}
log.info("转换完成,长度{}",wktList.size());
return RestResultUtils.success(wktList);
}
思路整理
- 判断文件类型
- 提取文件 or 提取流 (能力有限 ShapefileDataStore只找到从文件url创建的方法,选择提取文件
- 获取迭代器遍历数据,获取结果列表
- 关闭迭代器和流,返回结果
采坑总结
一、geotools版本不同,读取数据的写法也不相同
在设计之初,尝试用网上找到的遍历方法区读取数据,结果发现各种报错,最后是研究了之前同事的可行代码最终实现,可见geotools的版本对代码的兼容性不高,copy代码时也要仔细检查测试。
二、文件上传的中,transferTo方法的坑:部署后报错FileNotFoundException
解决的方法来源http://t.csdn.cn/7XXzL
使用transferTo在本地会报错,但是在linux部署环境下会报错如下
java.io.FileNotFoundException: /home/attachment/temp-file/temp.shx (No such file or directory)
解决方法:
使用外置工具提供的流拷贝方法,而不是用MultipartFile自带的方法
FileUtils.copyInputStreamToFile(file.getInputStream() , shapeFile);