Local Map From Mbtiles?

I've been searching for a way to use a local mbtiles file as a provider, has anyone had any luck with this?

thanks,
Ian

You’d need a server that knows how to read tiles out of the database in response to incoming requests. It’s not too hard - I wrote one in a couple hundred lines of Python that can search for available MBTiles packages, and handle incoming requests that match a /zoom/x/y format and either serve them out of the appropriate MBTiles file or off disk. Can’t share it, unfortunately, since it’s part of a project at work, but it’s pretty straightforward.

Hey Mark,

Thanks for the info and sorry for the late reply. If anyone else needs to implement a local mbtiles imagery provider, this is how I got started:

    var viewer = new Cesium.Viewer('cesiumContainer', {
        baseLayerPicker: false,
        imageryProvider: new Cesium.UrlTemplateImageryProvider({
            url: 'http://localhost:8081/{z}/{x}/{y}',
            minimumLevel:1,
            maximumLevel:5
        }),
        geocoder: false
    });

And a small node.js express server with sqlite3:

    var express = require('express');
    var sqlite3 = require('sqlite3').verbose();
    var dbName = 'C:/data/map.mbtiles';
    var db = new sqlite3.cached.Database( dbName, sqlite3.OPEN_READONLY,
        function ( err ) {
            if( err == null ) {
                console.log( dbName + ' ok');
            }
            else {
                console.log('Failed to open database \''+ dbName + ' ' + err );
            }
         });

    var app = express();

    // This responds a GET request for anything starting with a number
    app.get('/[0-9]*', function(req, res, next) {
        console.log("Got a GET request for /[0-9] (z/x/y) " + req.originalUrl );
        url = req.originalUrl.slice(1); // get rid of leading slash or it will result in an empty tokens[0] value
        var tokens = url.split("/",3); // limit of 3
        var zoom_lvl = tokens[0];
        var X = tokens[1];
        var Y = tokens[2];

        var stmt = "SELECT tile_data FROM tiles WHERE zoom_level=" + zoom_lvl + " AND tile_column=" + Y + " AND tile_row=" + X;
        db.all(stmt, function(err, rows) {
            if(err !== null) {
                console.log('ERROR:'+err);
                // Express handles errors via its next function.
                // It will call the next operation layer (middleware),
                // which is by default one that handles errors.
                next(err);
            }
            else {
                rows.forEach( function( row ) {
                console.log('Lvl:' + zoom_lvl +' Y:' + Y + ' X:'+ X );
                res.writeHead(200, {'Content-Type': 'image/png' });
                res.end( row.tile_data, 'binary');
            });
          }
      });
    })

var server = app.listen( 8081, function () {
   var host = server.address().address
   var port = server.address().port
   
   console.log("Example app listening at http://%s:%s", host, port)
})

Caveat: This is intended as a starting point. It is important to note that I do have an issue with the above code in that my displayed map is a little garbled. chunks of the world map get displayed in the wrong areas. I've tried swapping {y} for {reverseY} and other small attempts at fixing the problem, but no luck yet. If anyone has any clues please comment.

Cheers,
Ian

Any thoughts as to why this map is garbled?