> **本文回答**：上传 DWG → 获取 fileid → 创建 mapid → 打开地图 的完整流程；以及通过 URL、JSON 定义、`updateMap({filedoc})` 的三种特殊方式。

## 一、标准流程（前端上传 + 前端创建）

```html
<input type="file" id="fileInput" />
```

```js
document.getElementById("fileInput").onchange = async (e) => {
  const file = e.target.files[0];
  const svc = new vjmap.Service(SERVICE_URL, TOKEN);

  // 1) 上传
  const up = await svc.uploadMap(file);
  // up = { mapid: <建议名>, fileid: <唯一文件id>, uploadname: <原文件名> }

  // 2) （可选）用自己想要的 mapid
  const myMapid = "project-floor1";

  // 3) 创建地图：第一次用 mapid + fileid
  const res = await svc.openMap({
    mapid: myMapid,
    fileid: up.fileid,
    mapopenway: vjmap.MapOpenWay.GeomRender,
    style: vjmap.openMapDarkStyle()
  });
  if (res.error) throw new Error(res.error);

  // 4) 后续（刷新页面）只要 mapid 即可打开
  // await svc.openMap({ mapid: myMapid, mapopenway });
};
```

## 二、`uploadMap` 细节

`svc.uploadMap(file)` 内部步骤（对照 dist 源码）：

1. 读取文件 md5（`fileMd5`，分片读取）。
2. `GET {base}/map/mapfile?md5=...`（`checkFileHasUpload`）——若已存在返回 `{fileid, mapid, uploadname}`；否则进入 3。
3. `POST {base}/map/uploads?token=...`（FormData 字段名 `fileToUpload`）上传，返回 `{fileid, mapid, uploadname}`。
4. 建议 mapid 为 `"c"` + 文件 md5 前 11 位（图片为 `"t"` 前缀），确定性生成——同一文件得到同一建议名；可覆盖成自己的 mapid。

支持格式：默认 `.dwg` / `.dxf`（服务端 config `supportCadFormat` 可改）及图片 / PDF 等图像格式（以 `svc.cmdGetSupportFormat()` 返回为准）；其他后缀报 `not support format xxx`。

## 三、通过 URL 直接打开 DWG

服务端下载后打开，无需手工上传：

```js
await svc.openMap({
  mapid: "gym",
  fileid: "https://vjmap.com/static/assets/data/gym.dwg",
  mapopenway: vjmap.MapOpenWay.GeomRender
});
```

URL 末尾不是 `.dwg` 时：

```js
fileid: "https://host/getDwg?id=123&filetype=.dwg",
httpUsePost: true      // 复杂 URL 建议 POST
```

## 四、通过 JSON 定义直接建图（无需 DWG）

`updateMap({ filedoc })` 让服务端按 JSON 造一张 DWG。

```js
const doc = new vjmap.DbDocument();
doc.entitys = [
  new vjmap.DbLine({ start: [0, 0], end: [100, 100], colorIndex: 4 }),          // 构造时自动带 typename
  new vjmap.DbCircle({ center: [500, 500], radius: 200, colorIndex: 6 }),
  new vjmap.DbText({ position: [300, 300], contents: "Hello", height: 30 })
];

const res = await svc.updateMap({
  mapid: vjmap.getTempMapId(10),
  filedoc: JSON.stringify(doc),   // 必须是字符串（d.ts: filedoc?: string），传对象服务端读不到
  mapopenway: vjmap.MapOpenWay.Memory
});
```

手写 JSON 时每个实体必须有 `typename`（如 `"DbLine"`，缺省报 `need handle or typename!`），字段名按 d.ts 的 `IDbLine`/`IDbText` 等：直线 `start`/`end`、文字 `position`/`contents`（不是 `type`/`points`/`location`/`text`）。`doc.toDoc()` 得到的 `data:application/dwg;base64,...` 串也可直接作 `filedoc`。

详细 JSON 结构参考 [createMap 文档](https://vjmap.com/guide/createMap.html) 或 MCP 的 `createDwgDocHelper`。

## 五、后端 REST 上传（Node）

```js
const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");

async function uploadAndCreate(filepath, mapid) {
  const form = new FormData();
  form.append("fileToUpload", fs.createReadStream(filepath));
  const len = await new Promise((r, e) =>
    form.getLength((err, l) => (err ? e(err) : r(l)))
  );

  const up = await axios.post(`${BASE}/map/uploads?token=${TOKEN}`, form, {
    headers: { ...form.getHeaders(), "Content-Length": len }
  });
  // up.data.fileid, up.data.mapid

  const url =
    `${BASE}/map/openmap/${mapid || up.data.mapid}` +
    `?geom=true&fileid=${up.data.fileid}&uploadname=${up.data.uploadname}`;
  return axios.get(url, { headers: { token: TOKEN } });
}
```

## 六、上传时加密 / 限制 / 自定义字段

| 选项 | 说明 |
|---|---|
| `secretKey` | 首次创建时设密码（图加密） |
| `stylename` | 默认样式名 |
| `layeron/layeroff` | 初始图层显示/隐藏索引数组 |
| `clipbounds` | 初始裁剪范围 |
| `bkcolor` | 背景色（深色 0 / 浅色 0xFFFFFF） |
| `mapfrom` / `subfrom` | 协同图形来源（多图关联） |

## 七、覆盖已有 mapid：用 `updateMap`

`openMap` 对已存在的 `mapid` **不报错**：会忽略新传的 `fileid`、静默打开该图最新版本。要换成新文件必须调 `svc.updateMap(...)` 生成新版本（见 [map-management](map-management.md)）。

## 八、常见坑

1. **上传成功后立刻 openMap 报 "mapid 不存在"**：确认传了 `fileid`；第一次创建必须带。
2. **同一 DWG 多次 upload 得到不同 fileid**：后端按 md5 去重；首次 md5 check 未命中时会生成新 fileid，可能是因为文件略微变化（保存时间戳）。
3. **JSON 定义图 `filedoc` 传了对象 / 实体缺 `typename`** → 服务端读不到文档或报 `need handle or typename!`；用 `JSON.stringify(doc)` + `vjmap.DbLine` 等类构造实体。
4. **大文件 (>200MB)**：上传可能超时；服务端有大小限制，建议分片或调整 nginx `client_max_body_size`。
