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?

Hey, did you ever end up fixing this issue? I am trying to do a similar thing and my server works but it unfortunately isn’t showing up in the map.