9.3 KiB
DWG / DXF 网页查看器
浏览器端直接打开 DWG / DXF 图纸,不经过任何转换服务。界面沿用新迪 2D 查看器的模板 (顶栏 + 左侧图层面板 + 底部大图标工具栏 + 浮动子面板 + 状态栏)。
配套的 3D 版本在 ../STEPViewer/;两者的统一入口在 ../index.html(按文件后缀自动分发,
入口也支持拖拽打开,文件只在本机流转、不落地)。
一、能力
| 格式 | .dwg(LibreDWG 覆盖 R13 ~ R2018,越新的版本支持度越低)、.dxf(ASCII,UTF-8 / GBK 自动识别) |
| 实体 | LINE / CIRCLE / ARC / ELLIPSE / LWPOLYLINE / POLYLINE / SPLINE(NURBS+拟合点) / POINT / SOLID / 3DFACE / HATCH / TEXT / MTEXT / ATTRIB / DIMENSION / LEADER / MULTILEADER / INSERT(含阵列、嵌套、块内 0 层继承) |
| 显示 | 图层开关与单层隔离、真实线宽、线型(虚线/中心线)、ACI 与真彩色、三种背景(浅灰/米白/黑,同新迪 2D)、过暗/过亮线色按背景自动调整(可关)、剖面线(含 ANSI31~38 内置图案)、文字(中文、MTEXT 格式码/堆叠分数/按框宽折行) |
| 交互 | 滚轮定点缩放、拖动平移、框选放大、双击全图、视图旋转(设置里左转/右转 90° + 角度滑杆,旋转后拾取/测量/平移仍然准确)、点选查属性、对象捕捉(端点/中点/圆心/象限点/最近点) |
| 测量 | 坐标、点到点、连续、线段长、弧长、点到线、线到线(平行间距 / 夹角)、线性(ΔX/ΔY)、角度、半径直径、面积周长、结果统计;单位/小数位可调,已有结果跟着变 |
| 批注 | 文字、自由线、直线、箭头、矩形、圆、云线;颜色与线宽可调、可撤销(批注存世界坐标,跟着图纸缩放旋转) |
| 其它 | 文字全图查找并定位、模型/布局切换、PNG 截图、打印/导出 PDF、全屏(顶栏 + 底部工具栏各一个)、iframe 嵌入模式、上传加密存服务器并生成随机文件名的嵌入链接 |
实测(Edge headless,1500×950):
| 图纸 | 实体数 | 解析+展平 | 每帧重绘 |
|---|---|---|---|
| XQD601线图.dwg(542 KB,CAXA) | 3 865 | 340 ms | 3.1 ms |
| 行星滚柱丝杠专利图.dwg(2.0 MB) | 29 097 | 991 ms | 6.3 ms |
| 气垫调整机构.dxf(4.3 MB) | 21 732 | ~1.5 s | 8.8 ms |
二、目录
DWGViewer/
├── index.html 界面骨架(新迪 2D 模板)
├── style.css
├── app.js UI 装配:加载、图层面板、工具切换、面板、导出
├── js/
│ ├── source.js 文件 → 统一文档模型(分发 dwg / dxf,角度统一成弧度)
│ ├── dxfHatch.js DXF 的 HATCH 补丁解析(dxf-parser 不支持 HATCH)
│ ├── flatten.js 文档 → 显示列表(INSERT 递归展开、变换烘焙进坐标)
│ ├── curves.js 圆弧/椭圆/NURBS/bulge 离散化、二维仿射、紧包围盒
│ ├── hatch.js 填充边界提取 + 图案线生成(奇偶规则裁剪)+ 内置 acad.pat 图案表
│ ├── mtext.js MTEXT 格式码解析(\P \H \S \F {} 等)
│ ├── render.js Canvas2D 渲染器、空间索引、拾取
│ └── tools.js 对象捕捉、测量、批注
├── libs/
│ ├── dxf-parser/ MIT,DXF 解析(已改成浏览器可直接 import 的相对路径)
│ ├── shims/loglevel.js dxf-parser 依赖的 loglevel 替身(importmap 映射)
│ └── libredwg/ GPL-3.0,DWG 解析(dist 包装 + 10 MB wasm),只在打开 .dwg 时才加载
├── icons/ 取自新迪 2D/3D 案例的图标
└── samples/ 测试图纸
数据流:文件 → source.js → flatten.js → render.js。
展平只在加载时做一次,把 INSERT 的变换全部烘焙进世界坐标;之后缩放平移只重算屏幕坐标,
所以三万实体也能保持 6 ms 一帧。
三、本地运行
python $env:TEMP\nds_server_dwg.py # 端口 8920,服务 dev/ 根目录,日志 %TEMP%\req_log_dwg.txt
浏览器打开统一入口 http://127.0.0.1:8920/index.html,支持:
- 直接带参数(按后缀自动进 2D / 3D 查看器):
?file=DWGViewer/samples/XQD601.dwg、?file=STEPViewer/samples/as1-oc-214.stp - 落地页选文件 / 拖拽:文件内容经 postMessage 直接送进查看器,只在本机流转
- 单独打开查看器也行:
/DWGViewer/index.html?file=samples/XQD601.dwg
把 dwg/dxf 直接拖进页面也可以。
四、部署
纯静态站点,把整个目录传上去即可,没有服务端依赖。两个必须确认的点:
.wasm的 MIME 必须是application/wasm,否则 DWG 解析加载不起来。 Apache 用同目录的.htaccess;nginx 在mime.types里加application/wasm wasm;。- 开 gzip/br 压缩。
libredwg-web.wasm原始 10 MB,压缩后约 3 MB,差别很大。
嵌入到别的页面:
<iframe src="https://你的域名/DWGViewer/index.html?file=图纸路径.dwg&embed=1"
width="100%" height="640" frameborder="0" allowfullscreen></iframe>
embed=1 会隐藏顶栏。页面里的「嵌入」按钮可以直接生成这段代码。
启用防下载(api/*.php + .htaccess)后,图纸文件必须放在 DWGViewer 目录内(如
samples/xxx.dwg),路径写file=samples/xxx.dwg;../逃出查看器目录的路径 会被令牌通道拒绝(防目录穿越)。
五、许可证(重要)
| 模块 | 许可证 | 何时加载 |
|---|---|---|
| 本项目自身代码 | 自有 | 总是 |
dxf-parser |
MIT | 打开 .dxf 时 |
libredwg-web(LibreDWG) |
GPL-3.0 | 只有打开 .dwg 时才动态 import |
GPL-3.0 的传染性对前端是成立的:wasm 和 js 会下发到浏览器,这构成「分发」。 商用前请评估。三条可选路线:
- 只对内 / 接受 GPL —— 按 GPL-3.0 公开本查看器源码,最省事。
- 只支持 DXF —— 删掉
libs/libredwg/,source.js里的loadDwg直接抛错,整套依赖就只剩 MIT。 代价是用户得先把 DWG 另存成 DXF。 - DWG 解析挪到服务端 —— 用 LibreDWG 的
dwg2dxf命令行做 DWG→DXF(以独立进程调用, 通常被认为是「聚合」而非衍生作品),前端只留 MIT 的 DXF 路径;或换成 ODA SDK(商业授权)。
代码结构已经为此做了准备:source.js 里 DWG 只有 loadDwg() 一个入口,换掉它不影响其余任何模块。
六、已知限制
- SHX 字体不渲染真实字形。DWG 里的
.shx是矢量字库,浏览器读不了,这里按字体名映射到 系统字体(gbcbig/hztxt→ 宋体,txt/romans/isocp→ Arial)。字形和 AutoCAD 里有差异, 但内容、大小、位置、对齐都是对的。 - DIMENSION 画的是它的匿名块,也就是文件里存的那份图形,不会按标注样式重新排。 绝大多数情况这就是 AutoCAD 里看到的样子;只有别的软件生成的、没写块的标注会缺失。
- DXF 只支持 ASCII 格式。二进制 DXF 会给出明确提示,让用户另存。
- 非等比缩放 + 旋转的 INSERT 里的圆弧会退化成折线(等比或无旋转时保留解析曲线, 任意放大都不出锯齿)。这种组合在机械图里极少见。
- OLE、光栅图像(IMAGE)、代理实体(PROXY)不显示,会计入「跳过」统计。
$INSUNITS在国内图纸里常年是默认值,所以测量单位默认按毫米,可在「设置」里改。
七、防下载(已实现)
查看器读站内图纸时走「令牌 → 解密接口」,同时 .htaccess 封掉 .dwg/.dxf/.enc 的直接 GET:
- 上传(嵌入面板的「上传当前图纸」):
api/upload.php把图纸 gzip 后 XOR 加密落盘, 落盘名是纯随机 hex(uploads/ab12cd34….enc),原文件名藏在加密体里—— 链接里看不出是哪张图、属于哪个项目,也没法按名字猜其它图纸; - 读取:
api/token.php同源校验 + HMAC 短时令牌(5 分钟),api/model.php校验后 解密流式返回,原文件名通过X-Filename头带回来显示; .htaccess(站点根 +api/目录双层)禁止源文件直链。
app.js 的 fetchDrawing() 会自动走令牌流程;接口没部署(纯静态托管/本地 python)
时自动退回直连,不影响开发。部署 PHP 后无需任何前端改动。
部署注意:token.php / model.php / upload.php 里的 SECRET 三个文件必须一致,
并且要改掉默认值。uploads/ 目录要有写权限。
群晖/nginx(.htaccess 不生效):upload.php 和 model.php 已预设
$PRIVATE_DIR = '/volume1/dwgviewer_private';——在 File Station 里于 Web 目录外建这个
文件夹并给 http 用户组读写权限(路径不对就改成实际路径)。图纸存私有目录,嵌入链接写
?file=纯文件名.dwg;留在 Web 目录里的样例按原路径仍可打开,但可被直链下载,
要保护的文件必须移进私有目录。
网页端无法绝对防抓包(数据最终要进浏览器内存,懂行的人总能从调试台把解密后的字节导出来), 这套方案挡的是直接下载、批量爬取和链接外传后的猜名。