---
title: 地图管理（Map Management）
source: https://vjmap.com/guide/service/api/01-map-management.html
---

# 地图管理（Map Management）

> 分类 1 / 13 · 接口 15 个 · 

**快速目录**

| # | 接口 | 方法 | URL |
|---|------|------|-----|
| 1 | [秒传检测](#1-秒传检测-check_map_file) | GET | `/api/v1/map/mapfile` |
| 2 | [上传源文件](#2-上传源文件-upload_map) | POST | `/api/v1/map/uploads` |
| 3 | [打开/创建地图](#3-打开创建地图-open_map) | POST | `/api/v1/map/openmap/{mapid}` |
| 4 | [修改地图](#4-修改地图-update_map) | POST | `/api/v1/map/updatemap/{mapid}` |
| 5 | [关闭地图](#5-关闭地图-close_map) | GET | `/api/v1/map/cmd/closemap/{mapid}/{version}` |
| 6 | [删除地图](#6-删除地图-delete_map) | GET | `/api/v1/map/cmd/deletemap/{mapid}/{version}` |
| 7 | [重命名地图](#7-重命名地图-rename_map-已知不稳定) | GET | `/api/v1/map/cmd/renamemap/{old}/_` |
| 8 | [删除源文件](#8-删除源文件-delete_map_file) | GET | `/api/v1/map/cmd/deletemapfile/_/v1` |
| 9 | [列出地图](#9-列出地图-list_maps) | GET | `/api/v1/map/cmd/listmaps/_/v1` |
| 10 | [读元数据](#10-读元数据-metadata) | GET | `/api/v1/map/cmd/metadata/{mapid}/{version}` |
| 11 | [修改元数据](#11-修改元数据-update_metadata) | POST | `/api/v1/map/cmd/updateMetadata/{mapid}/{version}` |
| 12 | [缩略图](#12-缩略图-thumbnail) | GET | `/api/v1/map/cmd/thumbnail/{mapid}/{version}` |
| 13 | [支持的格式](#13-支持的格式-support_format) | GET | `/api/v1/map/cmd/supportFormat/_/v1` |
| 14 | [系统常量](#14-系统常量-const_data) | GET | `/api/v1/map/cmd/constData/_/v1` |
| 15 | [数据范围](#15-数据范围-get_data_bounds) | GET | `/api/v1/map/cmd/getDataBounds/{mapid}/{version}` |

**共性约定（重要）**

- 所有 `cmd/*` 路径：`GET` **不需要 body**，`POST` **要求 body 至少一个字段**，否则后端回 500 `param error`。SDK 对无 body 的 cmd 统一走 GET。
- `openmap` 通过 **POST body** 传 `mapid/version/fileid/uploadname/mapopenway`；`fileid ` 必须来自 `upload_map` 的返回，不要自己拼 md5。
- 所有路径都带 `?token=<JWT>`（SDK 自动加）。

---

## 1. 秒传检测 `check_map_file`

**URL**：`GET /api/v1/map/mapfile?md5={md5}`  
**用途**：客户端上传前先算文件 md5，若 `result:true` 则复用已有文件，跳过上传。

### 入参（Query）

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `md5` | string(32) | 是 | 源文件 MD5（小写 hex） |
| `token` | string | 是 | JWT |

### 出参

```json
{"result": false}
```

- `result=true`：已有同 md5 文件；可直接跳过上传用 `fileid = md5[:12]`
- `result=false`：需要走 `upload_map`

### 示例

```bash
curl -s "http://127.0.0.1:27660/api/v1/map/mapfile?token=$T&md5=caf27de8a2259b2c4e04f2afde2f5c42"
```

```python
svc.check_map_file("caf27de8a2259b2c4e04f2afde2f5c42")
```

```javascript
await svc.checkMapFile('caf27de8a2259b2c4e04f2afde2f5c42');
```

---

## 2. 上传源文件 `upload_map`

**URL**：`POST /api/v1/map/uploads`  
**Content-Type**：`multipart/form-data`  

### 入参（Form）

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `file` | binary | 是 | 源文件 |
| `md5` | string(32) | 是 | 预算的 MD5 |
| `secretKey` | string | 否 | 设置加密图的 16 位密钥；SDK 中默认空 |

### 出参

```json
{"fileid":"caf27de8a225","mapid":"caf27de8a225","uploadname":"caf27de8a225.dwg"}
```

- `fileid`：生成的**12 位十六进制**（= md5 前 12 位）
- `mapid`：默认等于 `fileid`；后续 `open_map` 可以给另一个业务名
- `uploadname`：服务端实际落盘的文件名

### 示例

```bash
curl -s -X POST "http://127.0.0.1:27660/api/v1/map/uploads?token=$T" \
  -F "file=@./my.dwg" \
  -F "md5=$(md5sum my.dwg | awk '{print $1}')"
```

```python
up = svc.upload_map("./my.dwg")
fileid, uploadname = up["fileid"], up["uploadname"]
```

```javascript
const up = await svc.uploadMap('./my.dwg');
const { fileid, uploadname } = up;
```

---

## 3. 打开/创建地图 `open_map`

**URL**：`POST /api/v1/map/openmap/{mapid}?version={version}` （SDK 默认走 POST；GET 等价）  

这是整套 API 的**中心接口**。它同时承担：

- 首次创建：`mapid` 未存在时结合 `fileid + uploadname` 新建
- 再次打开：`mapid` 已存在时忽略 `fileid/uploadname`
- 切换模式：`mapopenway` 决定是否拉起  渲染子进程

### 入参（JSON body）

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `mapid` | string | 是 | 业务 ID |
| `version` | string | 是 | 版本号，默认 `v1` |
| `fileid` | string(12) | **首次建图必填** | `upload_map` 返回的 fileid |
| `uploadname` | string | **首次建图必填** | `upload_map` 返回的 uploadname |
| `mapopenway` | `Memory` / `GeomRender` | 是 | 见 [`../02-conventions.md`](../02-conventions.md) |
| `style` | object | 否 | 预设样式；详情见 § 2 `create_map_style` |
| `secretKey` | string | 否 | 图级密钥 |
| `accessKey` | string | 否 | 全局 ak |
| `mapbounds` | array / string | 否 | 限制的图面范围 |

### 出参（节选，完整见 snapshot）

| 字段 | 含义 |
|------|------|
| `mapid / version / fileid / uploadname / filename` | 基本定位 |
| `bounds / dbBounds / drawBounds / initBounds / viewBounds` | 各种范围 |
| `layers` *(JSON string)* | 图层数组 |
| `styles` *(JSON string)* | 预置样式数组 |
| `format` | 瓦片格式（典型 `png`） |
| `mapopenway` | 实际使用的打开方式 |
| `pid` |  子进程 PID（GeomRender 时） |
| `renderAccuracy` | 渲染精度 |
| `isnewmap` | 是否刚创建 |

#### 真实响应片段

```json
{
  "mapid": "nb_roundtrip_1776829368",
  "version": "v1",
  "fileid": "caf27de8a225",
  "uploadname": "caf27de8a225.dwg",
  "filename": "caf27de8a225.dwg",
  "mapopenway": "Memory",
  "bounds": "[67108.08576259,-10253.62403246,73355.58576721,-4006.12402784]",
  "isnewmap": true,
  "format": "png",
  "layers": "[{\"color\":\"#ffffff\",\"index\":0,...}]",
  "styles": "[{\"backcolor\":0,\"isgeom\":false,...}]"
}
```

### 示例

```python
svc.open_map(
    mapid="demo_dwg", version="v1",
    mapopenway="Memory",
    fileid=up["fileid"], uploadname=up["uploadname"],
)
```

```javascript
await svc.openMap({
  mapid: 'demo_dwg', version: 'v1',
  mapopenway: 'Memory',
  fileid: up.fileid, uploadname: up.uploadname,
});
```

---

## 4. 修改地图 `update_map`

**URL**：`POST /api/v1/map/updatemap/{mapid}?version={version}`  

用法：修改 **已存在**图的属性（描述、可见性、部分字段等）。实现上等价于"带新参数再打开一次"，因此 body 通常和 `open_map` 类似，加上要改的字段。

### 入参（JSON body）

| 字段 | 必填 | 说明 |
|------|------|------|
| `mapid` | 是 | 要更新的图 |
| `fileid` | 是 | 必须和打开时一致 |
| `uploadname` | 是 | 同上 |
| `mapopenway` | 是 | 同上 |
| `description` | 否 | 描述 |
| `deleteOldVersion` | 否 | 删除旧版本再建 |
| …… | | 其余字段参考 `ServiceInterface.ts::IUpdateMapParam` |

### 出参

结构与 `open_map` 返回一致。

### 示例

```python
svc.update_map("demo_dwg", "v1", body={
    "mapid": "demo_dwg",
    "fileid": up["fileid"],
    "uploadname": up["uploadname"],
    "mapopenway": "Memory",
    "description": "添加二次开发示例描述",
})
```

---

## 5. 关闭地图 `close_map`

**URL**：`GET /api/v1/map/cmd/closemap/{mapid}/{version}`  

仅断开 图形服务 中的内存/渲染引用；不删除数据库文件，也不删图。

### 出参

```json
{"status": true}
```

### 注意：POST 无 body 会 500

```bash
# ✗ 500 param error
curl -X POST ".../closemap/sys_zp/v1?token=$T"
# ✓ 200
curl ".../closemap/sys_zp/v1?token=$T"
# ✓ 200（POST 可以，但 body 必须有至少一个字段）
curl -X POST ".../closemap/sys_zp/v1?token=$T" -d '{"fileid":"caf27de8a225"}' -H 'content-type: application/json'
```

SDK 内部统一使用 GET 规避该陷阱。

---

## 6. 删除地图 `delete_map`

**URL**：`GET /api/v1/map/cmd/deletemap/{mapid}/{version}?keepSource={bool}`  

| 参数 | 默认 | 说明 |
|------|------|------|
| `keepSource` | `true` | `true` 保留上传的源文件（只清元数据/DB），`false` 同时删源文件 |

### 出参

```json
{"status": true}
```

### 示例

```python
svc.delete_map("demo_dwg", "v1", keep_source=True)
```

---

## 7. 重命名地图 `rename_map`（**已知不稳定**）

**URL**：`GET /api/v1/map/cmd/renamemap/{old}/_?newmapid={new}`  

### 响应样例（实测）

```json
{
  "status": false,
  "error": true,
  "reason": "mapid is empty",
  "newmapid": "xxx_new",
  "AuthorityId": "root"
}
```

---

## 8. 删除源文件 `delete_map_file`

**URL**：`GET /api/v1/map/cmd/deletemapfile/_/v1?files=a.dwg;b.dwg`  

删除上传到 `data/mapfiles/` 目录下的物理文件。被删的文件**必须没有图在引用**。

### 出参（实测）

```json
{
  "deleted": [],
  "deletedCount": 0,
  "notFound": ["__nb_nonexistent__.dwg"],
  "status": false
}
```

### 示例

```python
svc.delete_map_file(["caf27de8a225.dwg"])
# 或字符串
svc.delete_map_file("a.dwg;b.dwg")
```

---

## 9. 列出地图 `list_maps`

**URL**：`GET /api/v1/map/cmd/listmaps/_/v1`  

### 入参

| Query | 说明 |
|-------|------|
| `keyword` | 按 mapid 过滤（可选） |
| `page` / `pageSize` | 分页（可选，多数版本支持） |

### 出参（实测）

```json
{
  "sys_zp": [
    {
      "db": "c47be46a2ad2.db",
      "filename": "c47be46a2ad2.dwg",
      "geom": true,
      "mtime": "2026-04-10 11:31:00",
      "status": "finish",
      "uploadname": "sys_zp.dwg",
      "version": "v1"
    }
  ]
}
```

- 顶层 key 是 `mapid`，value 是该图所有版本的数组
- `geom:true` 表示该图已有切片缓存
- `status:"finish"` 表示打开流程完成

### 示例

```python
maps = svc.list_maps()
for mapid, versions in maps.items():
    print(mapid, [v["version"] for v in versions])
```

```javascript
const maps = await svc.listMaps();
```

---

## 10. 读元数据 `metadata`

**URL**：`GET /api/v1/map/cmd/metadata/{mapid}/{version}`  

图必须先 `open_map` 打开才能读到完整元数据。

### 入参（Query）

| 字段 | 说明 |
|------|------|
| `enableEditMeta` | `true` 时返回可编辑字段；默认 `false` |
| `fileid` | 罕见用法：读源文件级元数据 |

### 出参（节选）

字段非常多，以下是二次开发最常用的子集：

| 字段 | 类型 | 含义 |
|------|------|------|
| `mapid / name / version / fileid / uploadname / filename` | string | 定位 |
| `bounds` | string("[minx,miny,maxx,maxy]") | 整图范围 |
| `dbBounds` / `drawBounds` / `initBounds` / `viewBounds` | string | 各阶段范围 |
| `createTime` / `time` / `mtime` | string | 时间戳 |
| `layers` | JSON 字符串（数组） | 图层列表 |
| `styles` | JSON 字符串（数组） | 样式列表 |
| `layouts` | string，逗号分隔 | 布局名 |
| `findFonts` / `preferableFonts` | JSON/字符串 | 字体字典 |
| `geomRecordCount` | string | 几何记录总数（估值） |
| `ucsorg` | string | UCS 原点矩阵 |
| `pid` | string |  进程 PID（仅 GeomRender） |



> ⚠ 注意：`layers` / `styles` / `findFonts` 等被序列化成**字符串**存在顶层；SDK 不会自动解嵌套 JSON，请按需 `json.loads()`。

### 示例

```python
svc.open_map("sys_zp", "v1", mapopenway="Memory",
             fileid="c47be46a2ad2", uploadname="sys_zp.dwg")
meta = svc.metadata("sys_zp", "v1")
layers = json.loads(meta["layers"])
```

---

## 11. 修改元数据 `update_metadata`

**URL**：`POST /api/v1/map/cmd/updateMetadata/{mapid}/{version}`  

通过 POST body 修改图的"用户可编辑字段"（通常是 description、layerOn 状态、业务标签等）。

### 入参（JSON body）

```json
{
  "fields": [
    { "name": "description", "value": "我是新的描述" },
    { "name": "tags",        "value": "building,sample" }
  ]
}
```

具体可编辑字段清单取决于后端版本；二次开发前可用 `metadata?enableEditMeta=true` 先探测。

### 出参

```json
{"status": true}
```

### 示例

```python
svc.update_metadata("demo_dwg", "v1", body={
    "fields": [{"name": "description", "value": "hello"}]
})
```

---

## 12. 缩略图 `thumbnail`

**URL**：`GET /api/v1/map/cmd/thumbnail/{mapid}/{version}?width=W&height=H[&layers=...][&backcolor=...]`  

返回 PNG 图片字节流。

### 常用参数

| Query | 说明 |
|-------|------|
| `width` / `height` | 缩略图像素大小 |
| `layers` | 仅渲染指定图层；逗号分隔 |
| `backcolor` | 背景色（`0xRRGGBB` 数字或 `#RRGGBB`） |

### SDK

```python
svc.open_map("sys_zp", "v1", mapopenway="GeomRender",
             fileid="c47be46a2ad2", uploadname="sys_zp.dwg")
png = svc.thumbnail_bytes("sys_zp", "v1", width=256, height=160)
open("thumb.png","wb").write(png)
```

```javascript
const buf = await svc.thumbnailBytes('sys_zp', 'v1', { width: 256, height: 160 });
fs.writeFileSync('thumb.png', buf);
```

也可以只构造 URL 直接嵌到 `<img src>`：

```python
url = svc.thumbnail_url("sys_zp", "v1", width=128, height=96)
# => http://127.0.0.1:27660/api/v1/map/cmd/thumbnail/sys_zp/v1?width=128&height=96&token=...
```

---

## 13. 支持的格式 `support_format`

**URL**：`GET /api/v1/map/cmd/supportFormat/_/v1`  

### 实测响应

```json
{
  "cad": "dwg;dxf",
  "image": "webp;heic;zip;png;pdf;jpg;jpe;jpc;heif;exif;avif;bmp;dib;tiff;hif;hdr;jfif;gif;tif;jpeg"
}
```

---

## 14. 系统常量 `const_data`

**URL**：`GET /api/v1/map/cmd/constData/_/v1`  

返回系统级字典，最常用的是 **CAD 实体类型号 → AcDb 类名** 的映射。

### 实测响应（节选）

```json
{
  "entTypeIdMap": {
    "1":  "AcDbLine",
    "2":  "AcDbPolyline",
    "5":  "AcDbSpline",
    "6":  "AcDbArc",
    "7":  "AcDbCircle",
    "10": "AcDbBlockReference",
    "11": "AcDbHatch",
    "12": "AcDbMText",
    "13": "AcDbText",
    "34": "AcDb3dSolid"
  }
}
```

搭配 `query_features` 的 `entType` 过滤参数使用。

---

## 15. 数据范围 `get_data_bounds`

**URL**：`GET /api/v1/map/cmd/getDataBounds/{mapid}/{version}`  

返回图上所有 **几何实体**的紧凑包围盒，比 `metadata.bounds`（可能含空图框）更贴合可见数据。

### 实测响应

```json
{
  "bounds": [
    587464241.0047014,
    3103794303.1750364,
    587769759.9828022,
    3104004303.209077
  ],
  "status": true
}
```

### 示例

```python
b = svc.get_data_bounds("sys_zp", "v1")["bounds"]
# 用来设置 vjmap 初始 fitBounds
```

---

- 

> 下一分类：[`02-tiles-and-styles.md`](02-tiles-and-styles.md)
