需求描述
要求上传一个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的propertiesfor (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);