概述
本文實現的是結合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; } }