Files
Leantime/dev/DWGViewer/说明.md

9.3 KiB
Raw Permalink Blame History

DWG / DXF 网页查看器

浏览器端直接打开 DWG / DXF 图纸,不经过任何转换服务。界面沿用新迪 2D 查看器的模板 (顶栏 + 左侧图层面板 + 底部大图标工具栏 + 浮动子面板 + 状态栏)。

配套的 3D 版本在 ../STEPViewer/;两者的统一入口在 ../index.html(按文件后缀自动分发, 入口也支持拖拽打开,文件只在本机流转、不落地)。


一、能力

格式 .dwgLibreDWG 覆盖 R13 ~ R2018越新的版本支持度越低.dxfASCIIUTF-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 headless1500×950

图纸 实体数 解析+展平 每帧重绘
XQD601线图.dwg542 KBCAXA 3 865 340 ms 3.1 ms
行星滚柱丝杠专利图.dwg2.0 MB 29 097 991 ms 6.3 ms
气垫调整机构.dxf4.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/     MITDXF 解析(已改成浏览器可直接 import 的相对路径)
│   ├── shims/loglevel.js  dxf-parser 依赖的 loglevel 替身importmap 映射)
│   └── libredwg/       GPL-3.0DWG 解析dist 包装 + 10 MB wasm只在打开 .dwg 时才加载
├── icons/              取自新迪 2D/3D 案例的图标
└── samples/            测试图纸

数据流:文件 → source.jsflatten.jsrender.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 直接拖进页面也可以。


四、部署

纯静态站点,把整个目录传上去即可,没有服务端依赖。两个必须确认的点:

  1. .wasm 的 MIME 必须是 application/wasm,否则 DWG 解析加载不起来。 Apache 用同目录的 .htaccessnginx 在 mime.types 里加 application/wasm wasm;
  2. 开 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-webLibreDWG GPL-3.0 只有打开 .dwg 时才动态 import

GPL-3.0 的传染性对前端是成立的wasm 和 js 会下发到浏览器,这构成「分发」。 商用前请评估。三条可选路线:

  1. 只对内 / 接受 GPL —— 按 GPL-3.0 公开本查看器源码,最省事。
  2. 只支持 DXF —— 删掉 libs/libredwg/source.js 里的 loadDwg 直接抛错,整套依赖就只剩 MIT。 代价是用户得先把 DWG 另存成 DXF。
  3. 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

  1. 上传(嵌入面板的「上传当前图纸」):api/upload.php 把图纸 gzip 后 XOR 加密落盘, 落盘名是纯随机 hexuploads/ab12cd34….enc),原文件名藏在加密体里—— 链接里看不出是哪张图、属于哪个项目,也没法按名字猜其它图纸;
  2. 读取:api/token.php 同源校验 + HMAC 短时令牌5 分钟),api/model.php 校验后 解密流式返回,原文件名通过 X-Filename 头带回来显示;
  3. .htaccess(站点根 + api/ 目录双层)禁止源文件直链。

app.jsfetchDrawing() 会自动走令牌流程;接口没部署(纯静态托管/本地 python 时自动退回直连,不影响开发。部署 PHP 后无需任何前端改动。

部署注意token.php / model.php / upload.php 里的 SECRET 三个文件必须一致, 并且要改掉默认值。uploads/ 目录要有写权限。

群晖/nginx.htaccess 不生效)upload.phpmodel.php 已预设 $PRIVATE_DIR = '/volume1/dwgviewer_private';——在 File Station 里于 Web 目录外建这个 文件夹并给 http 用户组读写权限(路径不对就改成实际路径)。图纸存私有目录,嵌入链接写 ?file=纯文件名.dwg;留在 Web 目录里的样例按原路径仍可打开,但可被直链下载, 要保护的文件必须移进私有目录。

网页端无法绝对防抓包(数据最终要进浏览器内存,懂行的人总能从调试台把解密后的字节导出来), 这套方案挡的是直接下载、批量爬取和链接外传后的猜名。