shape文件上传与展示

概述

本文讲述如何在OL中结合GeoTools实现shp数据的上传与展示。

流程

shp上传展示流程图

实现效果


线

使用技术

  1. jquery插件uploadify和ServletFileUpload实现shp文件的上传;
  2. ZipFile实现zip文件的解压;
  3. Geotools实现shp文件转换为geojson;
  4. openlayers4实现数据的展示。

实现代码

1、前端代码

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>shp文件</title>
    <link rel="stylesheet" href="//openlayers.org/en/v4.1.1/css/ol.css" type="text/css">
    <link rel="stylesheet" type="text/css" href="plugin/uploadify/uploadify.css">
    <style type="text/css">
        body, #map {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            font-size: 13px;
            overflow: hidden;
        }
        .map-tools{
            position: absolute;
            top:15px;
            right: 15px;
            z-index: 99;
            background: white;
            text-align: center;
            padding: 10px 10px 0 10px;
        }
        .modal-dialog {
            height: 100%;
            width: 100%;
            margin: 0;
            text-align: center;
        }
        .modal-dialog img {
            margin-top: 23%;
        }
    </style>
</head>
<body>
<div id="map">
    <div class="map-tools">
        <form action="" method="post" id="shp-upload" enctype="multipart/form-data">
            <input id="file_upload" name="file_upload" type="file" multiple="false">
        </form>
    </div>
</div>
<script src="//openlayers.org/en/v4.1.1/build/ol.js"></script>
<script type="text/javascript" src="plugin/jquery/jquery-3.1.1.min.js"></script>
<script src="plugin/uploadify/jquery.uploadify.min.js"></script>
<script type="text/javascript">
    var map;
    var vec_w = getTdtLayer("vec_w"),
        cva_w = getTdtLayer("cva_w");
    var source = new ol.source.Vector({
        features: []
    });
    var vector = new ol.layer.Vector({
        source: null,
        style:new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: '#ffcc33',
                width: 3,
                lineJoin: 'round',
                lineDash:[3,5]
            }),
            fill: new ol.style.Fill({
                color: 'rgba(255, 0, 0, 0.2)'
            }),
            image: new ol.style.Circle({
                radius: 6,
                fill: new ol.style.Fill({
                    color: '#3400ff'
                })
            })
        })
    });
    map = new ol.Map({
        controls: ol.control.defaults({
            attribution: false
        }),
        target: 'map',
        layers: [
            vec_w,
            cva_w,
            vector
        ],
        view: new ol.View({
            center: ol.proj.transform([104.214, 35.847], 'EPSG:4326', 'EPSG:3857'),
            zoom: 4
        })
    });

    $('#file_upload').uploadify({
        'formData': {},
        'successTimeout' : 600,
        'sizeLimit': 1024*1024,//限制大小
        'removeCompleted':true,
        'buttonText': '选择shp文件',
        'swf': 'plugin/uploadify/uploadify.swf',
        'uploader': 'shp-upload',
        'fileTypeExts': '*.zip',
        "onUploadSuccess": function (file, data, response) {
            var data = JSON.parse(data);
            addGeojson(JSON.parse(data.geojson))
        },
        "onUploadError": function (file, errorCode, errorMsg,
                                   errorString) {
            console.log(errorCode);
            console.log(errorMsg);
            console.log(errorString);
        }
    });

    function addGeojson(geojson){
        var features = (new ol.format.GeoJSON()).readFeatures(geojson);
        for(var i=0, l=features.length;i<l;i++){
            features[i].getGeometry().transform('EPSG:4326', map.getView().getProjection());
        }
        var source = new ol.source.Vector();
        source.addFeatures(features);
        vector.setSource(source);
    }

    function getTdtLayer(lyr) {
        var url = "http://t0.tianditu.com/DataServer?T=" + lyr + "&X={x}&Y={y}&L={z}";
        var layer = new ol.layer.Tile({
            source: new ol.source.XYZ({
                url: url
            })
        });
        return layer;
    }
</script>
</body>
</html>

2、后端代码

package com.lzugis.web.servlet;

import com.lzugis.helper.CommonMethod;
import com.lzugis.services.utils.ShpFormatUtil;
import com.lzugis.services.utils.ZipUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.json.simple.JSONObject;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by admin on 2017/9/10.
 */
@WebServlet(description = "shp file upload", urlPatterns =  {"/shp-upload"})
public class FileUploadServlet extends HttpServlet {

    private String rootPath = "";
    private ZipUtil zipUtil;
    private ShpFormatUtil shpUtil;
    private CommonMethod cm;

    public FileUploadServlet() {
        super();
        rootPath = "D:\\shppath\\";
        zipUtil = new ZipUtil();
        shpUtil = new ShpFormatUtil();
        cm = new CommonMethod();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        //1、创建一个DiskFileItemFactory工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //2、创建一个文件上传解析器
        ServletFileUpload upload = new ServletFileUpload(factory);
        //限制单个文件大小为1M
        upload.setFileSizeMax(1024*1024);
        //限制整个表单大小为1G
        upload.setSizeMax(1024*1024*1024);
        //解决上传文件名的中文乱码
        upload.setHeaderEncoding("UTF-8");
        factory.setSizeThreshold(1024 * 500);//设置内存的临界值为500K
        File linshi = new File(rootPath);//当超过500K的时候,存到一个临时文件夹中
        factory.setRepository(linshi);
        upload.setSizeMax(1024 * 1024 * 10);//设置上传的文件总的大小不能超过5M
        Map result = new HashMap<>();
        try {
            // 1. 得到 FileItem 的集合 items
            List<FileItem> /* FileItem */items = upload.parseRequest(request);
            // 2. 遍历 items:
            for (FileItem item : items) {
                // 若是一个一般的表单域, 打印信息
                if (item.isFormField()) {
                    String name = item.getFieldName();
                    String value = item.getString("utf-8");
                    System.out.println(name + ": " + value);
                }
                // 若是文件域则把文件保存到 e:\\files 目录下.
                else {
                    String fileName = item.getName();
                    long sizeInBytes = item.getSize();
//                    System.out.println(fileName);
//                    System.out.println(sizeInBytes);
                    InputStream in = item.getInputStream();
                    byte[] buffer = new byte[1024];
                    int len = 0;
                    //文件最终上传的位置
                    fileName = rootPath + fileName;
                    OutputStream out = new FileOutputStream(fileName);
                    while ((len = in.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                    out.close();
                    in.close();
                    String shpPath = zipUtil.unZipFiles(fileName, rootPath);
                    System.out.println("shp path"+shpPath);
                    StringBuffer json = shpUtil.shp2Json(shpPath);
                    result.put("status", "200");
                    result.put("geojson", json.toString());
//                    cm.append2File(rootPath + "json.json", json.toString());
                    JSONObject.writeJSONString(result, response.getWriter());
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }
}
···
3、zip解压类
```java
package com.lzugis.services.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class ZipUtil {
    /**
     * 解压文件到指定目录
     * 解压后的文件名,和之前一致
     * @param zipPath   待解压的zip文件路径
     * @param descDir   指定目录
     */
    @SuppressWarnings("rawtypes")
    public String unZipFiles(String zipPath, String descDir) throws IOException {
        String shpPath = "";
        File zipFile = new File(zipPath);
        ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));//解决中文文件夹乱码
        String name = zip.getName().substring(zip.getName().lastIndexOf('\\')+1, zip.getName().lastIndexOf('.'));
        File pathFile = new File(descDir+name);
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }
        for (Enumeration<? extends ZipEntry> entries = zip.entries(); entries.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            String zipEntryName = entry.getName();
            InputStream in = zip.getInputStream(entry);
            String outPath = (descDir + name +"/"+ zipEntryName).replaceAll("\\*", "/");
            // 判断路径是否存在,不存在则创建文件路径
            File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
            if (!file.exists()) {
                file.mkdirs();
            }
            // 判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
            if (new File(outPath).isDirectory()) {
                continue;
            }
            // 输出文件路径信息
            FileOutputStream out = new FileOutputStream(outPath);
            if(outPath.substring(outPath.length()-3,outPath.length()).equals("shp")){
                shpPath = outPath;
            }
            byte[] buf1 = new byte[1024];
            int len;
            while ((len = in.read(buf1)) > 0) {
                out.write(buf1, 0, len);
            }
            in.close();
            out.close();
        }
        return shpPath;
    }
}

4、shp文件转换

package com.lzugis.services.utils;

import com.amazonaws.util.json.JSONArray;
import com.amazonaws.util.json.JSONObject;
import com.vividsolutions.jts.geom.Geometry;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.geojson.feature.FeatureJSON;
import org.opengis.feature.simple.SimpleFeature;

import java.io.File;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

public class ShpFormatUtil {

    public StringBuffer shp2Json(String shpPath){
        StringBuffer sb = new StringBuffer();
        FeatureJSON fjson = new FeatureJSON();
        try{
            sb.append("{\"type\": \"FeatureCollection\",\"features\": ");

            File file = new File(shpPath);
            ShapefileDataStore shpDataStore = null;

            shpDataStore = new ShapefileDataStore(file.toURL());
            //设置编码
            Charset charset = Charset.forName("GBK");
            shpDataStore.setCharset(charset);
            String typeName = shpDataStore.getTypeNames()[0];
            SimpleFeatureSource featureSource = null;
            featureSource =  shpDataStore.getFeatureSource (typeName);
            SimpleFeatureCollection result = featureSource.getFeatures();
            SimpleFeatureIterator itertor = result.features();
            JSONArray array = new JSONArray();
            while (itertor.hasNext())
            {
                SimpleFeature feature = itertor.next();
                Geometry geo = (Geometry) feature.getAttribute("the_geom");

                StringWriter writer = new StringWriter();
                fjson.writeFeature(feature, writer);
                JSONObject json = new JSONObject(writer.toString());
                array.put(json);
            }
            itertor.close();
            sb.append(array.toString());
            sb.append("}");
        }
        catch(Exception e){
            e.printStackTrace();

        }
        return sb;
    }
}

技术博客
CSDN:http://blog.csdn.NET/gisshixisheng
博客园:http://www.cnblogs.com/lzugis/
在线教程
http://edu.csdn.Net/course/detail/799
Github
https://github.com/lzugis/
联系方式

类型 内容
qq 1004740957
公众号 lzugis15
e-mail niujp08@qq.com
webgis群 452117357
Android群 337469080
GIS数据可视化群 458292378
LZUGIS
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容