如何在 .net 核心中使用 Openstreetmap(osm) 离线图块文件?
How to use Openstreetmap(osm) offline tiles file in .net core?
我的 Web 应用程序使用 Leaflet
来显示一个小区域的地图。问题是应用程序必须脱机工作(在 LAN 上)并且地图图块是从 Openstreetmap
加载的。我下载了我需要的图块,但我没有找到关于如何使用下载文件的好文档(这是一个 500MB 的文件,扩展名为 .mbtiles)。这是 Leaflet 建议的默认方法:
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
如何使用 dotnet core
设置服务器以使用我的离线图块和给定参数并获取图块图像?(如下所示):
L.tileLayer('https://example.com/DotnetCore/WepApi/GetTiles?{s}/{z}/{x}/{y}').addTo(map);
这里是读取 tiles 文件并在您的 WebApi 中提供它们的基本实现。
您需要安装 NuGet System.Data.SQLite.Core(或类似软件)才能访问数据库。
助手class:
public class MbTilesReader
{
private string _mbTilesFilename;
public MbTilesReader(string mbTilesFilename)
{
_mbTilesFilename = mbTilesFilename;
}
public byte[] GetImageData(int x, int y, int zoom)
{
byte[] imageData = null;
using (SQLiteConnection conn = new SQLiteConnection(string.Format("Data Source={0};Version=3;", _mbTilesFilename)))
{
conn.Open();
using (SQLiteCommand cmd = new SQLiteCommand(conn))
{
cmd.CommandText = "SELECT * FROM tiles WHERE tile_column = @x and tile_row = @y and zoom_level = @z";
cmd.CommandType = System.Data.CommandType.Text;
cmd.Parameters.Add(new SQLiteParameter("@x", x));
cmd.Parameters.Add(new SQLiteParameter("@y", y));
cmd.Parameters.Add(new SQLiteParameter("@z", zoom));
SQLiteDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
imageData = reader["tile_data"] as byte[];
}
}
}
return imageData;
}
}
然后在您的 ConfigureServices 方法中将 class 注册为单例并传递文件路径:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new MbTilesReader("c:/temp/map.mbtiles"));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
最后,您可以 return 您的 WebApi 操作中的图像,如下所示:
[Route("api/[controller]")]
[ApiController]
public class MapController : ControllerBase
{
private MbTilesReader _tileReader;
public MapController(MbTilesReader tileReader)
{
_tileReader = tileReader;
}
[HttpGet]
public IActionResult Get(int x, int y, int z)
{
byte[] imageData = _tileReader.GetImageData(x, y, z);
return File(imageData, "image/png");
}
}
可能的改进
- 使用缓存来避免一直查询相同的图像。
- 使实现异步(参见 this 问题)。
编辑 - 格式
此答案假定您的数据以 PNG 格式存储,.mbtiles 文件可以以以下格式存储数据 pbf(用于矢量)、jpg、png 和 webapp。要了解您的数据库使用的是哪种格式,请检查 .mbtiles SQLite 数据库的 table 元数据中的数据。
有关详细信息,请参阅以下 link:https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md
我的 Web 应用程序使用 Leaflet
来显示一个小区域的地图。问题是应用程序必须脱机工作(在 LAN 上)并且地图图块是从 Openstreetmap
加载的。我下载了我需要的图块,但我没有找到关于如何使用下载文件的好文档(这是一个 500MB 的文件,扩展名为 .mbtiles)。这是 Leaflet 建议的默认方法:
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
如何使用 dotnet core
设置服务器以使用我的离线图块和给定参数并获取图块图像?(如下所示):
L.tileLayer('https://example.com/DotnetCore/WepApi/GetTiles?{s}/{z}/{x}/{y}').addTo(map);
这里是读取 tiles 文件并在您的 WebApi 中提供它们的基本实现。
您需要安装 NuGet System.Data.SQLite.Core(或类似软件)才能访问数据库。
助手class:
public class MbTilesReader
{
private string _mbTilesFilename;
public MbTilesReader(string mbTilesFilename)
{
_mbTilesFilename = mbTilesFilename;
}
public byte[] GetImageData(int x, int y, int zoom)
{
byte[] imageData = null;
using (SQLiteConnection conn = new SQLiteConnection(string.Format("Data Source={0};Version=3;", _mbTilesFilename)))
{
conn.Open();
using (SQLiteCommand cmd = new SQLiteCommand(conn))
{
cmd.CommandText = "SELECT * FROM tiles WHERE tile_column = @x and tile_row = @y and zoom_level = @z";
cmd.CommandType = System.Data.CommandType.Text;
cmd.Parameters.Add(new SQLiteParameter("@x", x));
cmd.Parameters.Add(new SQLiteParameter("@y", y));
cmd.Parameters.Add(new SQLiteParameter("@z", zoom));
SQLiteDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
imageData = reader["tile_data"] as byte[];
}
}
}
return imageData;
}
}
然后在您的 ConfigureServices 方法中将 class 注册为单例并传递文件路径:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new MbTilesReader("c:/temp/map.mbtiles"));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
最后,您可以 return 您的 WebApi 操作中的图像,如下所示:
[Route("api/[controller]")]
[ApiController]
public class MapController : ControllerBase
{
private MbTilesReader _tileReader;
public MapController(MbTilesReader tileReader)
{
_tileReader = tileReader;
}
[HttpGet]
public IActionResult Get(int x, int y, int z)
{
byte[] imageData = _tileReader.GetImageData(x, y, z);
return File(imageData, "image/png");
}
}
可能的改进
- 使用缓存来避免一直查询相同的图像。
- 使实现异步(参见 this 问题)。
编辑 - 格式
此答案假定您的数据以 PNG 格式存储,.mbtiles 文件可以以以下格式存储数据 pbf(用于矢量)、jpg、png 和 webapp。要了解您的数据库使用的是哪种格式,请检查 .mbtiles SQLite 数据库的 table 元数据中的数据。
有关详细信息,请参阅以下 link:https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md