ArcGIS Server提供的在线地图打印解决方案很简洁方便,通过ArcGIS Server发布一个PrintingTools服务,然后使用Javascript在Web前端创建一个PrintTask对象,设置好PrintParameters参数即可实现地图的在线输出.
require(["esri/tasks/PrintTask","esri/tasks/PrintTemplate", "esri/tasks/PrintParameters"], function(PrintTask, PrintTemplate, PrintParameters) {
var printurl = 'http://200.200.100.198/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task';
var printTask = new PrintTask(printurl);
var params = new PrintParameters();
var outWidth = (map.extent.xmax - map.extent.xmin) * 4600 /map.getScale();
var outHeight = (map.extent.ymax - map.extent.ymin) * 4600 /map.getScale();
var template = new PrintTemplate();
template.exportOptions = {
width: parseInt(outWidth),
height: parseInt(outHeight),
dpi: 96
};
template.format = "PNG32";//输出为png格式的图片
template.layout = "MAP_ONLY";
template.preserveScale = false;
params.map= map;
params.template = template;
printTask.execute(params, function (evt) {
window.open(evt.url, "_blank");
});
});
但是当我的地图网站发布到外网的服务器时,打印功能无法正常使用,但是之前在内网测试一切都是正常的。内网和外网有什么区别呢,如果是网络问题,地图都是可以正常显示的,只是打印功能不行。
最后发现跟路由器的NAT回流有关系。有关回流的解释可以参见这篇文章【http://zhan.renren.com/cqhqhsj?gid=3602888498000970436&checked=true】,感觉写的蛮清楚。这里需要说明一下网络环境。
服务器的内网地址比如假设是192.168.10.8,映射的外网地址200.200.100.198,ArcGIS Server和IIS都安装在这台服务器上。外网用户可以正常访问200.200.100.198发布的网站,并且可以正常看到网站里面的地图。
网站里面有一个输出地图的按钮应用,客户端点击这个按钮,实际是就是调用了上面的js文件,最终由ArcGISServer实时生成图片,并返回给客户端这张图片的地址,客户端打开这个地址就能看到图片。
如果外网环境下打印功能不行的话,问题只能是这个js文件。这个js文件中的PrintTask封装的太用力,有个过程我们看不到。ArcGIS Server是怎么生成图片的呢,应该是首先根据map对象获取到对应的地图服务【http://200.200.100.198:6080/arcgis/rest/services/MapServer】,因为一个地图服务就是一个mxd,ArcGIS Server基于这个mxd就可以进行切割合成图片了。
恰恰在这个过程中,因为NAT回流,获取的这个地图服务出了问题。客户端发出了请求http:// 200.200.100.198/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task,注意这个请求是带map对象的【params.map = map】;服务器收到请求后,会根据map对象获取到地图服务的地址【http://200.200.100.198:6080/arcgis/rest/services/MapServer】,然后服务器会访问这个地址,但是因为NAT回流,服务器访问不到这个地址,所以导致服务器无法正常生成图片。
这个问题可以怎么解决呢?我估计这是个常见问题,但是我在网上搜了搜,却发现GIS行业很少聊这个问题,很奇怪他(她)们是怎么解决的。
目前我发现只要绕开PrintTask,就可以解决。其一是PrintTask本质上就是向服务器发送http请求而已;其二是服务器访问200.200.100.198不可以,但是访问127.0.0.1总是可以的吧。
所以基于这两点,重新写了js文件,问题解决。
下面是代码:
function SnapshotMapFor() {
varwebMapAsJson = '{"mapOptions":{"showAttribution":true,"extent":{"xmin":{xmin},"ymin":{ymin},"xmax":{xmax},"ymax":{ymax},"spatialReference":{"wkid":21480}},"spatialReference":{"wkid":21480}},"operationalLayers":[{layers}],"exportOptions":{"outputSize":[2105,990],"dpi":96}}';
vargraphicsLayer = '{"id":"map_graphics","opacity":1,"minScale":0,"maxScale":0,"featureCollection":{"layers":[{"layerDefinition":{"name":"polygonLayer","geometryType":"esriGeometryPolygon"},"featureSet":{"geometryType":"esriGeometryPolygon","features":[{geometry}]}}]}}';
vargeometryJson = '{"geometry":{"rings":{rings},"spatialReference":{"wkid":21480}},"symbol":{"color":[3,169,244,26],"outline":{"color":[255,0,0,255],"width":1.5,"type":"esriSLS","style":"esriSLSSolid"},"type":"esriSFS","style":"esriSFSNull"}}';
webMapAsJson = webMapAsJson.replace("{xmin}",map.extent.xmin.toString());
webMapAsJson = webMapAsJson.replace("{xmax}",map.extent.xmax.toString());
webMapAsJson = webMapAsJson.replace("{ymin}",map.extent.ymin.toString());
webMapAsJson = webMapAsJson.replace("{ymax}",map.extent.ymax.toString());
varslayers = "";
for (vari = 0; i < map.layerIds.length; i++) {
if(map.layerIds[i] == 'map_graphics') {
}else {
var id = map._layers[map.layerIds[i]].id.toString();
var minScale = map._layers[map.layerIds[i]].minScale.toString();
var maxScale = map._layers[map.layerIds[i]].maxScale.toString();
var lurl = map._layers[map.layerIds[i]].url.toString();
lurl = lurl.replace('200.200.100.198', "127.0.0.1");//重点是这里做一个替换
slayers += '{"id":"';
slayers += id;
slayers += '","title":"';
slayers += id;
slayers += '","opacity":1,"minScale":';
slayers += minScale;
slayers += ',"maxScale":';
slayers += maxScale;
slayers += ',"url":"';
slayers += lurl;
slayers += '"},';
}
}
vargeostr = "";
for (vari = 0; i < map.graphics.graphics.length; i++) {
vartmpgeo = map.graphics.graphics[i];
if(tmpgeo.geometry.rings != null && tmpgeo.geometry.rings.length > 0){
var sring = RingToWKT(tmpgeo.geometry);
geostr += geometryJson.replace('{rings}', sring);
geostr += ",";
}
}
if(geostr == "") {
slayers = slayers.substring(0, slayers.length - 1);
} else{
geostr = geostr.substring(0, geostr.length - 1);
graphicsLayer = graphicsLayer.replace('{geometry}', geostr);
slayers += graphicsLayer;
}
webMapAsJson = webMapAsJson.replace("{layers}", slayers);
$.ajax({
url: 'http:// 200.200.100.198/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task/execute',
dataType: 'json',
beforeSend: function () {
},
data: {
Web_Map_as_JSON: webMapAsJson,
Format: "PNG32",
Layout_Template: 'MAP_ONLY',
returnZ: false,
returnM: false,
f: 'pjson'
},
type: 'post',
cache: false,
error: function (data) {
},
success: function (data) {
if (data != null) {
window.open(data.results[0].value.url, "_blank");
} else {
}
}
});
}
function RingToWKT(geometry) {
varwkt = [];
varrings = geometry.rings;
for (vari in rings) {
varring = rings[i];
for(var j in ring) {
var p = ring[j];
wkt.push('[' + p.toString() + ']');
}
}
return"[[" + wkt.join(",") + "]]";
}