概述
本文实现的是结合Openlayers4和java servlet实现公网资源切片的本地缓存。
优点
相比较其他下载利器,本实例具有以下优点: 1. 实现简单,操作简单; 2. 不会出现IP被封; 3. 结合web,看到哪下到哪,主动保存未缓存的切片; 4. 可通过修改URL和代码缓存多种地图切片。
缺点
鉴于web的实现,该切片缓存的方式具有以下缺点: 1. 被动式缓存,需要用户浏览需要下载的区域; 2. 无法批量缓存。 3. 主要是针对开发人员的,非开发人员使用有困难;
实现效果
实现思路
实现代码
页面代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>切片下载</title> <link rel="stylesheet" href="https://openlayers.org/en/v4.1.1/css/ol.css" type="text/css"> <style type="text/css"> body, #map { border: 0px; margin: 0px; padding: 0px; width: 100%; height: 100%; font-size: 13px; overflow: hidden; } </style> <script src="https://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 type="text/javascript"> var map; function init(){ var cva_w = getGeoheyLayer("blue"); var province = new ol.layer.Image({ source: new ol.source.ImageWMS({ ratio: 1, url: 'http://localhost:6080/geoserver/bj_grid/wms', params: { 'FORMAT': 'image/png', 'VERSION': '1.1.1', STYLES: '', LAYERS: 'bj_grid:bou2_4p', } }) }); map = new ol.Map({ controls: ol.control.defaults({ attribution: false }), target: 'map', layers: [cva_w, province], view: new ol.View({ center: ol.proj.transform([104.214, 35.847], 'EPSG:4326', 'EPSG:3857'), zoom: 4 }) }); } function getGeoheyLayer(style){ var url = "http://localhost:8081/lzugis-web/tile?layer="+style+"&z={z}&x={x}&y={y}"; var layer = new ol.layer.Tile({ source: new ol.source.XYZ({ url:url }) }); return layer; } </script> </head> <body onLoad="init()"> <div id="map"> </div> </body> </html>
servlet代码
package com.lzugis.web.servlet; import com.lzugis.web.helper.CommonConfig; import javax.imageio.ImageIO; 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.awt.image.BufferedImage; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; /** * Created by admin on 2017/9/10. */ @WebServlet(description = "wms services", urlPatterns = {"/tile"}) public class TileServiceServlet extends HttpServlet { private String url = "https://s4.geohey.com/s/mapping/"; private String tilepath = "d:/tile/geohey/"; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String x = request.getParameter("x"), y = request.getParameter("y"), z = request.getParameter("z"), layer = request.getParameter("layer"); StringBuffer tileUrl = new StringBuffer(); tileUrl.append(url); tileUrl.append(layer+"/all?"); tileUrl.append("z="+z+"&x="+x+"&y="+y); tileUrl.append("&retina=&ak=MGUxMmI2ZTk4YTVhNDEzYmJhZDJkNDM3ZWI5ZDAwOGE"); String tilefile = tilepath+layer+"/"+z+"/"+x+"_"+y+".png"; File tile = new File(tilefile); byte[] tileByte = null; /** * 如果文件存在,则直接读取文件 * 如果文件不存在,在先保存 */ if(tile.exists()){ tileByte = getFileBytes(tilefile); } else{ tileByte = getUrlBytes(tileUrl.toString()); saveTileFile(tileByte, tilefile); } OutputStream os = response.getOutputStream(); InputStream is = new ByteArrayInputStream(tileByte); try { int count = 0; byte[] buffer = new byte[1024 * 1024]; while ((count = is.read(buffer)) != -1) { os.write(buffer, 0, count); } os.flush(); } catch (IOException e) { e.printStackTrace(); } finally { os.close(); is.close(); } } private void saveTileFile(byte[] tileByte, String tilefile){ try { BufferedImage bi = null; bi = ImageIO.read(new ByteArrayInputStream(tileByte)); //判断文件夹是否存在,否则创建 File filetile = new File(tilefile); if (!filetile.getParentFile().exists()) { filetile.getParentFile().mkdirs(); } ImageIO.write(bi, "png", filetile); }catch (Exception e){ e.printStackTrace(); } } private byte[] getFileBytes(String tilefile){ byte[] buffer = null; try { File file = new File(tilefile); FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream bos = new ByteArrayOutputStream(1000); byte[] b = new byte[1000]; int n; while ((n = fis.read(b)) != -1) { bos.write(b, 0, n); } fis.close(); bos.close(); buffer = bos.toByteArray(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return buffer; } private byte[] getUrlBytes(String tilurl){ try { //new一个URL对象 URL url = new URL(tilurl); //打开链接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置请求方式为"GET" conn.setRequestMethod("GET"); //超时响应时间为5秒 conn.setConnectTimeout(5 * 1000); //通过输入流获取图片数据 InputStream inStream = conn.getInputStream(); //得到图片的二进制数据,以二进制封装得到数据,具有通用性 ByteArrayOutputStream outStream = new ByteArrayOutputStream(); //创建一个Buffer字符串 byte[] buffer = new byte[1024]; //每次读取的字符串长度,如果为-1,代表全部读取完毕 int len = 0; //使用一个输入流从buffer里把数据读取出来 while ((len = inStream.read(buffer)) != -1) { //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度 outStream.write(buffer, 0, len); } //关闭输入流 inStream.close(); //把outStream里的数据写入内存 return outStream.toByteArray(); } catch (Exception e) { e.printStackTrace(); } return null; } }