【问题总结+备忘录】上传一个shp文件能够读取其中的空间矢量字段,代码+采坑总结

需求描述

要求上传一个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);
}

思路整理

  1. 判断文件类型
  2. 提取文件 or 提取流 (能力有限 ShapefileDataStore只找到从文件url创建的方法,选择提取文件
  3. 获取迭代器遍历数据,获取结果列表
  4. 关闭迭代器和流,返回结果

采坑总结

一、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)

image-20230828093056981

解决方法:

使用外置工具提供的流拷贝方法,而不是用MultipartFile自带的方法

FileUtils.copyInputStreamToFile(file.getInputStream() , shapeFile);

你可能感兴趣的:(问题总结,备忘录,GIS相关,java,笔记)