Search code examples
javascriptcanvasdictionaryopenlayers-3wms

OpenLayers: 'Failed to execute 'toDataURL' on 'HTMLCanvasElement'


I have a problem when I try to export a map with multiple layer created using OpenLayer.
This is my JS code:

map.once('postcompose', function(event) {
       var img = new Image,
       canvas = event.context.canvas;

       img.crossOrigin = "anonymous";
       img.src = canvas.toDataURL('image/png');
});

Where map is the JavaScript variable of my OpenLayers map.
When the map is composed of more than one level, I receive this kind of error:

Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported

If a try to do the same thing without adding level to the map (just using the default OpenLayer map) I am able to generate the data URL and download the map in png format.
It seems to be a CrossOrigin problem, but the CORs should be enabled on my server.
Any help? Thanks!

EDIT
Here it is the JS code example where I add the layer to the map that is causing this issues.

var layer = new ol.layer.Image({
     source: new ol.source.ImageWMS({
        url: 'http://pubblicazioni.provincia.fi.it/geoserver/wms',
        params: {
                'LAYERS': 'layer_name',
                'FORMAT': 'image/png',
                'TRANSPARENT': 'true'
        },
        crossOrigin: null
     })
});
map.addLayer(layer);

Solution

  • I solved the problem implementing a local proxy on my server as suggested by MichaelJS.
    I'm running a Django app, so I developed a customized proxy starting from this code:
    https://github.com/mjumbewu/django-proxy

    Then in my urls.py I defined this rule:

    url(r'^proxy/(?P<url>.*)$', views.proxy_view, name='proxy'),
    

    And finally I proxed the request to the WMS service changing the JS code this way:

    var layer = new ol.layer.Image({
         source: new ol.source.ImageWMS({
            url: '/proxy/http://pubblicazioni.provincia.fi.it/geoserver/wms',
            params: {
                    'LAYERS': 'layer_name',
                    'FORMAT': 'image/png',
                    'TRANSPARENT': 'true'
            },
            crossOrigin: null
         })
    });
    map.addLayer(layer);
    

    CrossOrigin issue solved!