I have web application that uses Leaflet
to show map of a small region. The problem is that the application must work offline(on LAN) and map tiles are loaded from Openstreetmap
. I downloaded the tiles that I needed but I haven't find a good documentation about how to use the downloaded file(which is a 500MB file with .mbtiles extension). Here is the default approach suggested by 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);
How do I set up a server using dotnet core
to use my offline tiles and given parameters and get tiles images?(like the following):
L.tileLayer('https://example.com/DotnetCore/WepApi/GetTiles?{s}/{z}/{x}/{y}').addTo(map);
Can I use your map tiles? We are in principle happy for our map tiles to be used by external users for creative and unexpected uses - in contrast to most web mapping providers. However, the OpenStreetMap servers are run entirely on donated resources.
OpenMapTiles is an open-source project aiming to create world maps from open data. It consists of a set of tools allowing everyone to create their own vector map tiles from OpenStreetMap data for hosting, self-hosting, or offline use. It is available as free software on OpenMapTiles.org.
Here is a basic implementation to read the tiles file and serve them in your WebApi.
You need to install the NuGet System.Data.SQLite.Core (or similar) to access the database.
Helper 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;
}
}
Then register the class as a singleton in your ConfigureServices method and pass the path to the file:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new MbTilesReader("c:/temp/map.mbtiles"));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Finally, you can return the image in your WebApi action as follows:
[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");
}
}
Possible improvements
Edit - Formats
This answer assumes your data is stored in PNG format, .mbtiles files can store data in the following formats pbf (for vectors), jpg, png, and webapp. To know which format your database is using, check the data in the table metadata of the .mbtiles SQLite database.
See the following link for more info: https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With