geoserver rest方式发布shp服务
工作需求,要在Web端提供发布shp服务的功能,并且能够使用户对shp图层的样式进行编辑。样式编辑属于后话了,现在还没到达这一步,只是把shp服务发布做完了(样式采用默认的)
基本访问方法
我们知道使用rest方式访问geoserver,很多功能都需要认证(Authorization)信息,否则是获取不到实际数据的。所以我们需要在请求头里面加上Authorization,使得客户端具有访问的权限。
如果是用jquery/webpack-zepto的话,那么就
const fetchList = () => {
let results = null
$.ajax({
url: 'geoserver/rest/layers.json',
dataType: 'json',
type: 'GET',
async: false,
success: (result) => {
results = result.layers.layer
},
headers: {
'Authorization': 'Basic YWRtaW46Z2Vvc2VydmVy'
}
})
return results
}
注意ajax参数中的url,因为我用nginx做了代理,使得访问不像是跨域。由于在headers中加入了认证信息,浏览器会先options方式请求,这样就导致第一次请求的失败,因为geoserver并没有为options请求方式提供对应的接口,它会提示403,就是说它理解了这次请求并拒绝了你,感觉就像是女孩说的话。
至于这个认证信息,就是BASE64对geoserver用户名密码的编码。我的是admin:geoserver,注意这个格式,然后去base64加密,如果账号信息没有修改过,跟我的一样,YWRtaW46Z2Vvc2VydmVy就直接拿去用吧
为了方便,我把nginx配置文件也亮出来吧
server {
listen 8040;
server_name localhost;
location /geoserver/ {
proxy_pass http://localhost:8080;
proxy_redirect off;
}
location / {
proxy_pass http://localhost:8030;
proxy_redirect off;
}
}
其中8040是系统应用的端口,将来向外网映射时也会用这一个。
当访问localhost:8040/geoserver/时,就会转发至geoserver服务地址,其余都会转发至我的nodejs服务器。
shp发布
言归正传,前面只是举例说明一下访问geoserver的一些基本操作,下面进行shp发布
// 发布
$('#new_pubtn').on('click', function () {
// validate data integrity
// ...
let file = $('#new_file')[0].files[0]
let option = {
workspace: $('#new_workspace').val(),
datastore: $('#new_datastore').val(),
type: $('#new_type').val(),
file: file,
name: file.name.substring(0, file.name.indexOf('.'))
}
utils.publish(option)
})
这段代码很简单,通过字面意思就很容易明白各项所代表的含义了,就不再展示html怎么写了。总之这几项是我发布shp的几个必须字段(除了那个type吧。。。)
下面看看发布方法
const publish = (option) => {
let results = null
if (option.type === 'VECTOR') {
let formData = new window.FormData()
formData.append('file', option.file)
$.ajax({
url: 'geoserver/rest/workspaces/' + option.workspace + '/datastores/' + option.datastore + '/file.shp?charset=GB2312',
type: 'PUT',
async: false,
data: formData,
contentType: false,
processData: false,
headers: {
'Authorization': 'Basic YWRtaW46Z2Vvc2VydmVy',
'Content-type': 'application/zip'
},
success: (data, textStatus, jqXHR) => {
if (jqXHR.status === 201) {
fixPublish(option)
}
}
})
}
return results
}
我发现如果不再url后面追加charset=GB2312这种编码格式,服务中的字段值都是一些乱码,至少我发布的几个服务都是出现了乱码(有中文的)。
上传的shapefile必须要先打包成zip,这是官网说的,只能照做。注意打包时shapefile不能包含在文件夹中,就是说把shapefile的一系列文件选中后右键“添加到压缩文件…”而不是把shapefile放到文件夹中再压缩。
当服务器返回201时,就表示创建成功了。
fix bug
官网说就好了,表示“Uploads files to the data store ds, creating it if necessary”,这个“if necessary”是什么鬼?查看geoserver发现datastore确实已经创建了,但是打不开。。。
而且这个图层也没有发布,预览也是不可能的。
工作中一直用的是CGCS2000坐标系,而geoserver默认的是4326,所以如果不是WGS84坐标系的话,就需要这个“fix bug”
当我在geoserver中为发布失败的图层进行手动发布时,才发现shp之所以没有发布时因为没有定义srs,为什么。。。翻出几个月前自己写的也是shp发布的代码,原来配置文件也要修改,一刹那感觉自己以前这么厉害,简直大神啊。
<featureType>
<srs>EPSG:4490</srs>
<projectionPolicy>FORCE_DECLARED</projectionPolicy>
<enabled>true</enabled>
</featureType>
这几行代码是我很久之前通过比较两者(手动shp发布和代码提交发布)配置文件featuretype.xml是发现的
于是
const fixPublish = (option, index = 0) => {
let results = null
let content = null
let url = null
if (option.type === 'VECTOR') {
url = 'geoserver/rest/workspaces/' + option.workspace + '/datastores/' + option.datastore + '/featuretypes/' + option.name + (index === 0 ? '' : index)
content = '<featureType><srs>EPSG:4490</srs><projectionPolicy>FORCE_DECLARED</projectionPolicy> <enabled>true</enabled></featureType>'
}
$.ajax({
url: url,
type: 'PUT',
async: false,
data: content,
headers: {
'Authorization': 'Basic YWRtaW46Z2Vvc2VydmVy',
'Content-type': 'text/xml'
},
success: (data, textStatus, jqXHR) => {
if (jqXHR.status === 200) {
results = '发布成功!'
}
},
error: (jqXHR, textStatus, errorThrown) => {
if (jqXHR.status === 404) {
index++
// 当超过10次时,放弃
if (index <= 10) {
fixPublish(option, index)
}
}
}
})
return results
}
至于这个index,当我们对一个shp提交多次以后,哪怕datastore不同,shp后面中是会添加相应的数字以区分之前提交shp,比如我提交data.zip,里面压缩的是dahong.shp,第一次图层的名称是dahong,第二次提交就是dahong1,第三次dahong2…
因为名称和datastore不同,又无法获知你提交过相同的shp多少次,所以就这么写了,确实有点儿心机boy的感觉
我还想说…
目前工作就先做到这里了,明天回家过年。谢谢各位捧场,有什么错别字或者不理解的地方欢迎下面留言