Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is that possible to load a shapefile (zip) from an api ? #61

Open
ToHold opened this issue Nov 14, 2019 · 5 comments
Open

Is that possible to load a shapefile (zip) from an api ? #61

ToHold opened this issue Nov 14, 2019 · 5 comments

Comments

@ToHold
Copy link

ToHold commented Nov 14, 2019

Hello ! First, thanks for this awesome project.

I'm currently developping an app that use leaflet and shapefile. But I'm also using an api that authenticate users with a JWT. Each users have some shapefile to load, so I would need to add authentication headers to "new L.Shapefile()".

Is that possible ? If yes how could I do it ?

@GoGeophysical
Copy link

ToHold, "new L.Shapefile('myurl')" syntax works fine for me. HOWEVER, it seems picky with a requirement that your url path end with a ".zip", which is not self-evident.

@ToHold
Copy link
Author

ToHold commented Nov 18, 2019

Thanks for you answer,

But I've found a way to do what I wanted :).

let shape = shp(apiurl + "/api/shape/" + acquisition.name + '.zip', undefined,[{name:'Authorization',value:'Bearer ' + usertoken}]).then(function(geojson){ // console.log(geojson); geojson.features.forEach(feature => { feature.properties.name = acquisition.name; feature.properties.city = acquisition.data.ville; feature.properties.date = acquisition.data.date; feature.properties.path = apiurl + "/api/acquisition/"+ acquisition.name + '/entwine.json'; feature.properties.type = 'ENT'; feature.properties.from = 'internet'; feature.properties.details = acquisition.data; feature.properties.selected = false; }); var myLayer = L.geoJSON(geojson, { style: function (feature) { return {color: acquisition.data.couleurgeoview}; } }).addTo(map); });

See I've just added a parameter named "headers" at these function :

function shp(base, whiteList, headers) { if (typeof base === 'string' && cache.has(base)) { return Promise.resolve(cache.get(base)); } return shp.getShapefile(base, whiteList, headers).then(function (resp) { if (typeof base === 'string') { cache.set(base, resp); } return resp; }); }

shp.getShapefile = function(base, whiteList, headers) { if (typeof base === 'string') { if (base.slice(-4) === '.zip') { return getZip(base, whiteList, headers); } else { return Promise.all([ Promise.all([ binaryAjax(base + '.shp'), binaryAjax(base + '.prj') ]).then(function(args) { return parseShp(args[0], args[1] ? proj4(args[1]) : false); }), binaryAjax(base + '.dbf').then(parseDbf) ]).then(shp.combine); } } else { return new Promise(function(resolve) { resolve(shp.parseZip(base)); }); } };

function getZip(base, whiteList, headers) { return binaryAjax(base,headers).then(function(a) { return shp.parseZip(a, whiteList); }); }

function binaryAjax(url,headers){ return new Promise(function(resolve,reject){ var type = url.slice(-3); var ajax = new XMLHttpRequest(); ajax.open('GET',url,true); headers.forEach(header => { ajax.setRequestHeader(header.name, header.value); }); if(type !== 'prj'){ ajax.responseType='arraybuffer'; } ajax.addEventListener('load', function (){ if(ajax.status>399){ if(type==='prj'){ return resolve(false); }else{ return reject(new Error(ajax.status)); } } resolve(ajax.response); }, false); ajax.send(); }); }

@ToHold
Copy link
Author

ToHold commented Nov 18, 2019

And for downloading a zip from api, I've used Symfony Headers, and Lexik JWT Token.

@ToHold
Copy link
Author

ToHold commented Nov 18, 2019

And so I do not use leaflet.shapefile, but shp.js and L.geoJSON from leaflet.

@DistChen
Copy link

you can use ArrayBuffer.

there is a mistake in leaflet.shpfile.js (line 44),you should change isArrayBufer to isArrayBuffer, see #65.

then you can use:

fetch("http://exmaple.com/1")
	.then(resp => resp.arrayBuffer())
	.then(data => {
		let layer = new L.Shapefile(data, {
		      isArrayBuffer:true
		});
		layer.addTo(map);
		layer.once("data:loaded", function() {
			map.fitBounds(layer.getBounds());
		});
	});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants