OpenLayers 3 – Avoiding CORS Errors

corsopenlayers

The CORS error seen is:

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

All this doesn't work:

OpenLayers 3: Cross-Origin Request Blocked: The Same Origin Policy disallows

Enabling CORS in OpenLayers

https://stackoverflow.com/questions/20260620/openlayers-3-and-xyz-layer ( the exemple jsfiddle don't even work)

Can't do this (I don't own the server):

http://enable-cors.org/

I'm tring to save my map as PNG (http://openlayers.org/en/v3.0.0/examples/export-map.html).

The example works nice in my server with only the OSM layer, but when I add one more layer from anywhere, I got the CORS error.

My application allow the user to add arbitrary layers from any getMap link, so I have no control over the source Geoserver.

I have an addLayer function to do the job (add the user's layer to the map).

function addLayer( serverUrl, serverLayers, layerName ) {
    var newLayer = new ol.layer.Tile({
        source: new ol.source.TileWMS({
            url: serverUrl,
            isBaseLayer : false,
            crossOrigin: 'anonymous',  <<<<--- PROBLLEM
            params: {
                'layers': serverLayers,
                'format': 'image/png'
            },
            projection: ol.proj.get('EPSG:4326')
        })
    }); 
    newLayer.set('name', layerName);
    map.addLayer( newLayer );
    return newLayer;
}

When I add the crossOrigin: 'anonymous' nothing works anymore. Without crossOrigin it work if the map have only the OSM layer. By adding any other layer I got the CORS error.

Is there any other way to get the Map as image than using the canvas?

I've searched over all this site and found many different answers but none worked.

I cannot configure server side.

This is my export function:

function exportMap() {
    map.once('postcompose', function(event) {
        var canvas = event.context.canvas;
        var xx = canvas.toDataURL('image/png'); <<------- CORS Error !!
        console.log( xx );
    });
    map.renderSync();   
}

Best Answer

Unfortunate, what you are experiencing, is expected behavior, and not a Bug.

Once you add an Image from an external domain, or cross-domain, and use it on the canvas, the canvas becomes "tainted" and the browser will not allow you to pull data out of it.

The only solution for this is two step:

  1. Proper headers need to be sent by the server, which is sending you the images

  2. The crossOrigin attribute on the image itself in the JavaScript. In OpenLayers, you can do this by using crossOrigin: 'anonymous' in the layer settings. For example:

    var wms_layer=new ol.layer.Tile({
      extent: [-13884991, 2870341, -7455066, 6338219],
      source: new ol.source.TileWMS({
        url: 'http://demo.boundlessgeo.com/geoserver/wms',
        params: {'LAYERS': 'topp:states', 'TILED': true},
        serverType: 'geoserver',
        crossOrigin: 'anonymous'
      })
    });

Now I know that you do not have control over the server, so you cannot do the first step.

In-case the server allows it, you could have a proxy on your own server, which serves these tiles, and the whole issue will be side-stepped.