首页 / 资讯中心 / 文章详情

ArcGIS REST API 实践指南:端点选型、参数与排查技巧

ArcGIS REST API 实践指南:端点选型、参数与排查技巧 ★ FEATURED ARTICLE
做 GIS 数据对接和地图页面开发的这几年我养成了一个习惯每隔一段时间就把项目里用到的 ArcGIS REST API 接口重新拉一遍核对服务地址、图层 ID、坐标系、字段名和 Token 有效期。因为这套接口不像 SDK 那样给你一堆封装好的类它把服务能力摊开成一个个 HTTP 地址服务目录、图层查询、要素编辑、空间分析全靠 URL 参数来驱动。本文就是一份 ArcGIS REST API 的实践记录把我经常用、也容易踩坑的端点、参数和排查方法整理在一起。如果你在做数据接入、自动化报表、Web 地图前端或者需要把 GIS 服务能力集成到业务系统里这页笔记应该能节省不少试错时间。很多时候网上教程只告诉你“怎么调通一次”却没人说“拿到地址之后该记哪些信息”。所以我这篇不是复制官方文档而是站在实操角度把接口从“能通”讲到“能长期用”。1. 先搞清 ArcGIS REST API 到底在什么位置刚接触 ArcGIS REST API 的人最容易犯的错是把重点放在“怎么写代码”上结果连服务目录结构都没看明白。其实这套接口的规律性很强只要理解了一次访问过程后面各种服务都能举一反三。1.1 一个 URL 就是一类能力ArcGIS Server 或 Portal 发布服务后所有能力都会按照固定路径暴露出来。顶层是服务目录下面挂地图服务、要素服务、影像服务、地理处理服务等类型。通常一个地址长这样https://your-server/arcgis/rest/services/城市基础/MapServer把最后一段从MapServer换成FeatureServer可能就是同一个数据源的可编辑版本换成GPServer则可能是一个工具服务。记住这个层级关系就能做到看到 URL 就大致猜出服务类型。ArcGIS REST API 的每个操作也基本是“服务地址 操作名 参数”。比如查询图层地址是https://your-server/arcgis/rest/services/城市基础/MapServer/3/query后面的query就是操作名前面/3/是图层 ID。参数里带where11、outFields*、returnGeometrytrue、fjson之类。整个接口没有复杂的 SDK 概念核心就是 URL 和参数。注意这条路径中的端口号、站点名不一定固定。很多单位部署时会自己在前面套一层网关或反向代理实际访问地址和服务器内部地址可能不一样。记录接口时先把“业务系统实际访问的地址”和“服务器管理员给的原始地址”分开记。1.2 记录时要先看目录而不是猜参数拿到一个新服务地址我的习惯是先打开服务目录看一眼而不是直接拼一个查询参数去试。在浏览器访问服务地址末尾加?fjson就能看到这段 JSON 里包含的关键信息{ serviceDescription: 城市基础数据, maxRecordCount: 2000, supportedQueryFormats: JSON, geoJSON, PBF, capabilities: Map,Query,Data, layers: [] }这段 JSON 比任何文档都诚实。它告诉你这个服务能做什么、最多返回多少条记录、支持哪种格式。比如supportedQueryFormats里写了geoJSON前端就可以直接用fgeojson没写的话老老实实继续用fjson别盲目依赖第三方库的自动转换。目录里的layers数组还包含了每个图层的 ID、名称、几何类型、字段列表、空间参考信息。我建议每次打通接口后把这个目录 JSON 存一份在本地作为后续开发、联调、排查的基线。1.3 打开“?fjson”时到底看哪些字段同样一个?fjson新手可能只看有没有 layers老手会多看几个字段。重点信息可以整理成一张清单字段含义为什么重要maxRecordCount单次查询最大返回条数决定分页逻辑怎么写capabilities服务能力集合判断只读还是可编辑supportedQueryFormats支持响应的数据格式决定能不能用 GeoJSONspatialReference服务原生坐标系坐标转换的基础fullExtent数据全集范围空间过滤边界参考initialExtent初始化显示范围前端初始化地图时会用到其中capabilities最容易忽略。有的服务看起来是 FeatureServer但管理端只开了Query没开Editing代码里调用增删改接口就会一直报 403 或“操作不可用”。提前看目录能省掉大量摸黑排查时间。2. 端点选型MapServer 和 FeatureServer 别用混很多文章把 ArcGIS REST API 笼统说成“一个 URL 就完事”但真要接入业务系统时选错服务类型会带来两种完全不同的结果一种是你调了半天写不进去另一种是数据读得太慢。所以先把服务类型分清楚。2.1 MapServer 适合只读和地图展示MapServer 是原生的“地图服务”最擅长的是把地理数据组织成图层然后按照空间范围、比例尺、图例渲染出来。常见操作包括export按范围、大小、图层透明度输出一张地图图片identify根据屏幕坐标或地理坐标点击识别图层属性find跨图层搜索某个字段值返回匹配要素legend获取图层的符号图例query按属性和空间条件查询要素举个例子如果前端要做“点击图层查看详情”最适合的不是把整张表数据拉到前端再自己算而是直接调用 MapServer 的identify操作https://your-server/arcgis/rest/services/城市基础/MapServer/identify ?geometry-122.2,37.5 geometryTypeesriGeometryPoint mapExtent-122.3,37.4,-122.1,37.6 layersall tolerance5 fjson这个请求会让服务端根据当前地图范围、点击位置和容差把范围内的要素属性返回给你。效率很高也避免了把大量数据推到前端。但 MapServer 的query只能读不能写。如果想在前端交互中让用户新增、修改、删除要素MapServer 做不到需要切到 FeatureServer。提示identify的mapExtent是必需参数很多人漏了它导致结果为空或报错。如果你只是做纯属性查询用query就可以了不需要走identify。2.2 FeatureServer 才是能写数据的地方FeatureServer 是要素服务本质上是在 MapServer 基础上叠加了编辑能力。它最常见的操作有query查询要素返回几何和属性addFeatures新增要素updateFeatures更新要素deleteFeatures删除要素applyEdits在一个请求里混合新增、更新、删除applyEdits是项目里最常用的。它支持 JSON 格式的 features 数组比如新增一个点要素POST https://your-server/arcgis/rest/services/城市基础/FeatureServer/0/applyEdits请求体大致是{ adds: [ { attributes: { NAME: 测试点, CODE: A001 }, geometry: { x: 120.1, y: 30.2, spatialReference: { wkid: 4326 } } } ], f: json }这里要特别注意objectId字段通常由服务端自动生成新增时不要传否则可能报唯一值冲突更新时必须传对象 ID否则服务端不知道你要改哪条记录。这些细节在目录 JSON 的字段定义里都能看到。判断一个 FeatureServer 是否能写最直接的办法是看目录 JSON 的capabilities字段。里面包含Create、Update、Delete、Editing等关键字才说明它开了编辑权限。只看到Query的话就算调用applyEdits也只会得到错误。2.3 ImageServer 和其他服务类型也顺手记一下除了 MapServer 和 FeatureServer实际项目里还会遇到 ImageServer、GPServer。ImageServer 主要面向影像数据例如卫星影像、栅格数据常见操作是exportImage和getSamples返回的是影像或采样值不是矢量要素。GPServer 则是地理处理服务它把模型或脚本发布成工具调用时用submitJob提交任务、jobResults查询结果。这些服务日常用得没前两类频繁但记录接口时一定要在文档里标注服务类型。因为不同服务类型对应的操作名完全不一样同一段代码如果只改了端点后缀很可能直接报“找不到操作”。3. 实操从拿 Token 到完成一次空间查询接下来进入正题一个完整的 ArcGIS REST API 调用过程到底要经历哪些环节。我以一个常见场景为例登录服务、查询某个范围内的设施点、把结果字段取出来用于业务展示。3.1 先拿 Token别把密码写在请求里ArcGIS Server 的接口是否需要 Token取决于服务是否公开。很多单位的服务都是内网加密的调用必须带 Token。Token 的获取方式不同版本稍有差别Portal 环境常用POST https://your-server/arcgis/sharing/rest/generateToken请求参数usernameyour_username passwordyour_password refererhttps://your-app-server fjson返回 JSON 里会有token字段例如{ token: abc123..., expires: 1700000000000, ssl: true }拿到 Token 后后续请求可以放在 URL 的token参数里也可以放在请求头X-Esri-Authorization: Bearer token里。放在 URL 里调试时很直观但如果 Token 出现在访问日志里会泄露权限信息所以正式生产环境建议用请求头。注意Token 有时效性短则几十分钟、长则数小时具体看服务端配置。脚本里不要写死 Token每次运行前重新获取或者先判断expires时间再决定是否刷新。我见过不少线上故障都是因为凌晨定时任务跑的时候 Token 恰好过期任务失败后又没有人看日志。3.2 Query 参数逐个拆解where、outFields、returnGeometry查询操作是所有接口中使用频率最高的但很多人喜欢直接复制一个“万能模板”却不知道每个参数为什么这样写。我的习惯是逐个拆解参数示例作用where11SQL 风格的过滤条件outFieldsNAME,CODE只返回需要的字段returnGeometrytrue是否返回几何信息outSR4326输出坐标系fjson返回格式举个最小示例https://your-server/arcgis/rest/services/城市基础/MapServer/3/query ?where11 outFieldsNAME,CODE returnGeometrytrue outSR4326 fjsonwhere11是查询全部数据的经典写法。因为where必须是合法 SQL 表达式11永远为真所以等价于不设过滤。但它容易让前端把全量数据拉下来正式环境一定要加上更严格的条件比如按区域、状态字段过滤。outFields尽量只写需要的字段。有的图层有几十个字段如果写*返回的 JSON 会非常庞大。尤其在地图拖动、异步加载场景下响应体积直接影响页面性能。returnGeometrytrue表示返回每条要素的空间坐标。如果只是做属性校验或者统计数量改成false响应量会小很多。3.3 空间查询的参数组合geometry、spatialRel、inSR纯属性查询比较简单一旦涉及空间查询参数就多了。ArcGIS REST API 里最常用的空间查询组合是geometrygeometryTypespatialRelinSR。例如我在地图上画了一个矩形框想查这个矩形框内所有设施点请求是这样的https://your-server/arcgis/rest/services/城市基础/MapServer/3/query ?where11 geometry-122.2,37.4,-122.0,37.6 geometryTypeesriGeometryEnvelope spatialRelesriSpatialRelIntersects inSR4326 outSR4326 outFieldsNAME,CODE fjson这里geometry的四组数字表示矩形框的xmin,ymin,xmax,ymaxgeometryTypeesriGeometryEnvelope告诉服务端这是一个外包矩形inSR4326声明这个矩形的坐标系spatialRelesriSpatialRelIntersects表示只要要素与矩形有交集就返回。空间关系还可以换成esriSpatialRelContains、esriSpatialRelWithin、esriSpatialRelTouches等。我的经验是Intersects最常用但要做严格的“完全包含”关系时必须用Contains或Within否则边界重叠的记录会被误判。注意坐标顺序不能写反。写成ymin,xmin,ymax,xmax会返回空结果因为服务端判断不了这个范围。排查空间查询无数据时第一件事就是检查坐标顺序和inSR是否与前端坐标系一致。3.4 用 POST 做大量参数请求浏览器地址栏里能用 GET 调通的接口在生产环境不一定适合。因为where复杂时中文、括号、单引号都要做 URL 编码地址会变得很长还容易被网关截断。我的建议是凡是参数多的查询统一用 POST 提交表单数据。Python 里用requests写起来很直观import requests url https://your-server/arcgis/rest/services/城市基础/FeatureServer/0/query params { where: STATUS 1 AND NAME LIKE %测试%, outFields: NAME,CODE,STATUS, returnGeometry: false, outSR: 4326, f: json, token: token, } resp requests.post(url, dataparams, timeout30) data resp.json() for feature in data.get(features, []): attrs feature[attributes] print(attrs[NAME], attrs[CODE])POST 方式对参数编码更友好也方便统一管理超时、代理、重试逻辑。我在自动化脚本里基本都用 POST只有临时调试才用 GET。4. 把接口记录变成能长期维护的文档前面讲的都是“怎么调通”但在真实项目里接口记录的价值在于“可维护”。服务更新、图层结构调整、坐标系变更都会让之前的代码突然崩掉。所以我建议把 ArcGIS REST API 信息做成一张标准清单而不是散落在聊天记录里。4.1 需要记录的元信息清单每接入一个服务我至少记录以下内容类别具体内容访问地址实际业务地址、原始服务地址服务类型MapServer / FeatureServer / ImageServer / GPServer图层编号同一个服务下多个图层各自的 ID图层名称图层显示名称有些中文名称会重复几何类型点、线、面、多点原生坐标系服务数据源的 SR比如3857、4326、4490关键字段业务主键、名称字段、状态字段权限状态是否需要 Token、编辑能力是否开启最大记录数maxRecordCount值更新时间服务最近一次验证的日期这些信息不需要手工复制直接从服务目录 JSON 里读取就行。我经常做完一次服务盘点后把结果存成 Markdown 表格再附一份原始 JSON 作为附件项目验收、交接新人时都很省事。4.2 用脚本自动盘点图层如果服务数量很少手工记录没问题但如果一个系统下挂了几十个服务、上百个图层手工就不现实了。我会写一个递归脚本从根目录开始遍历所有 services 和 folders自动打印出每个服务的图层清单。import requests import json base_url https://your-server/arcgis/rest/services token your_token def list_layers(service_url): resp requests.get(service_url, params{f: json, token: token}) data resp.json() for layer in data.get(layers, []): print(layer[id], layer[name], layer.get(geometryType)) for table in data.get(tables, []): print(table, table[id], table[name]) def walk_folders(folder_path/): url base_url folder_path resp requests.get(url, params{f: json, token: token}) data resp.json() for service in data.get(services, []): print(service[name], service[type]) if service[type] MapServer: list_layers(base_url / service[name] /MapServer) elif service[type] FeatureServer: list_layers(base_url / service[name] /FeatureServer) for folder in data.get(folders, []): walk_folders(folder_path / folder)这个脚本可以做成定时巡检任务每周跑一次比较前后两次的图层列表。如果某个图层被删了、字段改了脚本能最早发现而不是等业务系统报错才知道。4.3 记录字段别名和编码域字段名通常是英文别名才是业务人员认识的中文名。比如字段叫STATUS别名是“状态”值域里可能定义了0代表“停用”、1代表“在用”。写接口记录时要把别名和值域也存下来。{ name: STATUS, alias: 状态, type: esriFieldTypeString, domain: { type: codedValue, codedValues: [ { name: 停用, code: 0 }, { name: 在用, code: 1 } ] } }在前端展示时我通常用别名做表头写入数据时再通过编码域把界面文字转成对应的数字或代码。这个转换逻辑如果不记录后面接手的同事看到STATUS0会完全不知道是什么意思。5. 常见问题与排查技巧实录ArcGIS REST API 的报错信息不像普通 Web 接口那么友好很多提示是“Unable to complete operation”这种笼统描述。但大部分坑其实有固定套路掌握之后能很快定位。5.1 error 400、498、499 代表什么HTTP 状态码是排查接口问题的第一现场。400 Bad Request参数错误。通常是漏了必填参数、参数类型不对、where 语句语法有问题。做法是检查 URL 里的fjson、geometryType、outSR是否齐全。498 Invalid TokenToken 非法或已过期。重新生成 Token 再看。499 Token Required请求需要 Token 但没传。确认是否在 URL 或请求头带了 TokenToken 是否被网关过滤。500 Internal Server Error服务端处理失败常见原因是数据源连接异常或查询条件太复杂。此时要看服务端日志客户端往往拿不到详细堆栈。我见过一个很典型的 498 场景脚本里用requests.get默认把参数编码到 URL但 Token 本身包含/等特殊字符在某些网关里会被解码改变。解决方法是把 Token 放到 Header 里或者改用 POST 提交。5.2 中文查询结果为空中文条件过滤是高频问题。比如whereNAME LIKE %北京%如果直接在浏览器地址栏粘贴中文空格会被浏览器部分转义但送到服务端时编码不对结果就是返回 0 条但也不报错。我的经验是中文条件查询尽量用 POST让 HTTP 库自动处理 UTF-8 编码。如果只能用 GET那也要先对where做 URL 编码再用requests或 Postman 调试。另外where里的字符串值要用英文单引号包裹例如whereNAME LIKE %北京%这里的单引号不是中文引号写错会导致 SQL 拼接错误。提示如果返回结果为空先在服务目录里手动执行一次fjson确认数据源是否有数据。很多时候不是查询参数问题而是这个图层本身就没有记录或者图层被设置了权限过滤。5.3 返回要素太多接口很慢ArcGIS REST API 的maxRecordCount限制了单次最多返回多少条但即使只有 2000 条如果每次带着完整几何和几十个字段返回也会很慢。排查慢接口时我会先做三件事加returnCountOnlytrue看看总数到底有多少判断是不是全表查询。加空间过滤或where条件缩小范围。outFields只保留业务需要的字段减少序列化体积。如果要分批拉取大量数据分页参数是resultOffset和resultRecordCount。示例https://your-server/arcgis/rest/services/城市基础/FeatureServer/0/query ?where11 resultOffset0 resultRecordCount500 outFieldsOBJECTID,NAME returnGeometryfalse fjson下一页就把resultOffset变成 500、1000。不过分页拉取时要注意数据是否在查询过程中被修改否则会出现跳条或重复。对于只读分析场景我更推荐用whereOBJECTID 上次最大值的方式滚动读取稳定性更好。5.4 坐标对不上地图位置偏移地图位置偏移通常不是接口的问题而是坐标系没对齐。服务源数据可能是3857前端地图用4326如果请求里没有outSR4326返回的就是以服务原始坐标系表达的点前端叠加到另一套坐标系上自然错位。正确的做法是查询接口统一加outSR让它输出前端需要的坐标系空间查询输入时声明inSR告诉服务端你传入的坐标是什么坐标系不要在浏览器前端再做一次神秘的“坐标偏移”魔法容易越改越乱如果服务坐标是 CGCS2000 等国内常用坐标系需要注意服务端版本是否支持对应的 WKID。有的老版本服务不识别某些新 WKID会直接报错或返回空。这时要么换用同椭球下的近似坐标系要么在服务端做一次数据源转换两种情况都要在接口记录里写清楚“实测可用坐标系”。6. 一点个人经验和小工具记录做久了多少会总结出一些顺手的小工具和习惯。放在最后纯粹是因为这些东西不算必须的官方知识但确实能提高效率。6.1 浏览器是最好用的接口调试器调试 ArcGIS REST API我经常直接打开浏览器在地址栏里访问服务地址然后加?fjson。浏览器会把返回的 JSON 自动格式化缩进、层级一目了然。Chrome 或 Edge 还支持直接在地址栏搜索 JSON 里的字段比 Postman 还要快。需要把请求串起来组合查询时我会先用浏览器的“开发者工具”里的网络面板找到已经成功的查询请求右键复制为fetch或cURL再放进脚本里改参数。这样能保证请求头、编码方式和服务端实际接收到的请求完全一致。6.2 自动化巡检比被动维护省心我上面提到过定期跑目录遍历脚本这里再补充一个实际用法把脚本放到定时任务里每天生成一份 JSON 快照。哪天有第三方系统反馈字段不对、图层丢失我直接把昨天的快照和今天的快照做对比几秒钟就能定位变更点。这个习惯成本很低收益却很高。GIS 服务有时会被管理员在后台调整例如给图层加一个字段、关掉一个能力这些调整不会主动通知业务方。只有通过巡检才能提前发现问题。6.3 关于“记录”这件事我的体会是它要一直更新我最早也以为 ArcGIS REST API 记一次就够了后来发现不同服务器版本、不同数据源、不同服务配置接口参数细节都会有一点差异。比如同样一个where条件在某套环境里支持中文别名查询在另一套环境里只支持字段英文名查询同样一个空间查询一个服务用Intersects能返回边界点另一个服务可能需要Touches。所以我现在每接通一个服务都会在接口记录末尾写上一行“实测日期、实测环境、可用参数组合”。这不是文档洁癖而是知道这些信息在使用时才最可靠。希望这份 ArcGIS REST API 记录也能帮你少走几次弯路。
阅读完成 · 觉得有帮助?
咨询建站