如何为地图的选定部分下载 OSM 瓦片

How to download the OSM tiles for selected part of map

我想使用 Openlayer OSM 层为地图的选定部分离线下载地图,具有单一缩放级别。我有地图的四个角,即地图的显示部分。

但需要获取所有的瓷砖图像或四个角之间的瓷砖。我回顾了一些例子:

https://gis.stackexchange.com/questions/167792/how-to-retrieve-the-tile-url-in-openlayers-3

但我需要在客户单击按钮时下载磁贴。谁能帮帮我。

这里有一个简单的示例,可以将图块保存为数据 URL 供以后使用。如果您需要保存的图块在关闭并重新打开浏览器后仍然可用,请将 sessionStorage 替换为 localStorage。

// load OSM zoom level 8 tiles for Switzerland to data urls

var extent = ol.proj.transformExtent([5.9,45.8,10.55,47.85],'EPSG:4326','EPSG:3857');
var zoom = 8;

var source = new ol.source.OSM();

source.getTileGrid().forEachTileCoord(extent, zoom, function(tileCoord) {
    var img = document.createElement("img");
    img.onload = function() {
        var canvas = document.createElement("canvas");
        canvas.width = source.getTileGrid().getTileSize(zoom);
        canvas.height = source.getTileGrid().getTileSize(zoom);
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0);
        sessionStorage.setItem('OSM_' + tileCoord[0] + '_' + tileCoord[1] + '_' + (-tileCoord[2]-1), canvas.toDataURL());
        img.remove();
        canvas.remove();
    };
    img.crossOrigin = "Anonymous";
    img.src = source.getTileUrlFunction()(tileCoord);
});

// wait a few seconds to ensure data urls are ready, then create a map to use them

setTimeout(function(){

    map = new ol.Map({
        target: 'map',
        layers: [
            new ol.layer.Tile({
                extent: extent,
                source: new ol.source.XYZ({
                    attributions: ol.source.OSM.ATTRIBUTION,
                    maxZoom: 8,
                    minZoom: 8,
                    tileUrlFunction: function(tileCoord) {
                        return sessionStorage.getItem('OSM_' + tileCoord[0] + '_' + tileCoord[1] + '_' + (-tileCoord[2]-1));
                    }
                }),
            })
        ],
        view: new ol.View({
            center: ol.extent.getCenter(extent),
            zoom: 8
        }),
        controls: ol.control.defaults({
            attributionOptions: { collapsible: false },
        })
    });

}, 3000);

您可以在 C# 上编写简单的 Web 客户端 例如:

static void Main(string[] args)
        {
double[] latitudes= new double[] { 38.822591, 40.979898, 43.068888, 45.089036, 47.040182, 48.922499, 50.736455, 52.48278, 54.162434, 55.776573, 57.326521, 58.813742, 60.239811, 61.606397, 62.915233, 64.168107, 65.366837, 66.51326, 67.60922, 68.656555, 69.657086, 70.612614, 71.524909, 72.395706, 73.2267, 74.019543, 74.775843, 75.497157, 76.184995, 76.840817, 77.466029, 78.061989, 78.630006, 79.171334, 79.687184, 80.178713, 80.647035, 81.093214, 81.518272, 81.923187, 82.308893, 82.676285, 83.026219, 83.359512, 83.676943, 83.979259, 84.267172 };// see netzwolf.info kashebrowser
for (int kk = 0; kk < 45; kk++)
            {
                string currentToken = "546882";//osm token, you can view it in cookies
                String lat1 = "," + latitudes[kk] + ",";
                String lat2 = "," + latitudes[kk + 1];
                double long1= 18.671225;
                double deltaLong1 = 5.0104;// you can get in v
                for (i = 32; i < 48; i++)
                {

                    try
                    {
                        using (WebClient client = new WebClient())
                        {

                            String currentUrl = "https://render.openstreetmap.org/cgi-bin/export?bbox=" + long1.ToString() + lat1+ (long1+ deltaLat1).ToString() + lat2+ "&scale=4000000&format=svg";//format and scale
                            Console.WriteLine(currentUrl);
                            Uri url = new Uri(currentUrl);
                            client.Headers.Add(HttpRequestHeader.Authorization, "render.openstreetmap.org");
                            client.Headers.Add("method", "GET");
                            client.Headers.Add("scheme", "https");
                            client.Headers.Add(HttpRequestHeader.Accept, "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
                            //client.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate, br");
                            client.Headers.Add(HttpRequestHeader.AcceptLanguage, "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7");
                            client.Headers.Add(HttpRequestHeader.Cookie, "_osm_totp_token=" + currentToken);
                            client.Headers.Add("sec-ch-ua", "\"Chromium\";v=\"88\", \"Google Chrome\";v=\"88\", \"; Not A Brand\";v=\"99\"");
                            client.Headers.Add(HttpRequestHeader.Referer, "https://www.openstreetmap.org/");
                            client.Headers.Add("sec-fetch-dest", "document");
                            client.Headers.Add("sec-fetch-mode", "navigate");
                            client.Headers.Add("sec-fetch-site", "same-site");
                            client.Headers.Add("sec-fetch-user", "?1");
                            client.Headers.Add("upgrade-insecure-requests", "1");
                            client.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36");
                            client.QueryString.Add("format", "svg");
                            Console.WriteLine(i);
                            client.DownloadFile(url, i.ToString() + "_" + kk.ToString() + ".svg");
                            long1+= deltaLong;

                        }
                    }
//if server drop, it wait 5 sec get token  again and get back one iteration
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                        System.Threading.Thread.Sleep(5000);
                        String currentUrl = "https://www.openstreetmap.org/#map=8/41.8368/104.5450&layers=N";
                        HttpWebRequest tQ = (HttpWebRequest)HttpWebRequest.Create(currentUrl);
                        tQ.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9";
                        tQ.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.41 YaBrowser/21.2.0.1097 Yowser/2.5 Safari/537.36";
                        tQ.ContentType = "text/html; charset=utf-8";
                        tQ.Referer = currentUrl;
                        HttpWebResponse tS = (HttpWebResponse)tQ.GetResponse();
                        string tC = tS.Headers["Set-Cookie"];
                        var cc = tC.IndexOf("_osm_totp_token=");
                        currentToken = tC.Substring(cc + "_osm_totp_token=".Length, 6);
                        //string num = tC.Trim(, 2);
                        Console.WriteLine(tC);
                        i = i - 1;
                    }

                    Console.WriteLine("i=" + i.ToString());
                }

            }
}