CAD 图纸在线预览:格式选型与转换链路
客户丢过来一个 DWG,问"能不能在网页里看一眼"。这个需求听起来像前端问题,实际上是文件格式问题——浏览器从来没有打算认识 CAD 图纸。
一、先认清格式
机械行业的图纸基本跑不出这几类,处理难度差别很大:
| 格式 | 性质 | 处理难度 |
|---|---|---|
| 已经是版式文件 | 低,浏览器/PDF.js 直接渲染 | |
| DXF | 文本结构的矢量图 | 中,解析实体后自己画 |
| DWG | Autodesk 私有二进制 | 高,必须经转换器 |
| STEP / IGES | 三维 B-rep 实体 | 高,需要几何内核 |
| STL / 3MF | 三角网格 | 低,three.js 直接加载 |
二维和三维是两条完全不同的管线,不要试图用一套代码吃掉。二维的目标是"看清标注",三维的目标是"看清形状",对精度的要求正好相反。
二、DWG 的三条路,以及为什么选本地转换
要让浏览器看到 DWG 内容,本质上只有三条路:
- 调用商业 SDK。ODA、Autodesk 都有现成方案,效果最好,成本和授权最重。
- 用云服务转换。上传后拿到图片或 PDF,省事,但图纸是客户的,出门这一步在制造业里过不去。
- 本地开源转换器。LibreDWG 这类项目能把 DWG 转成 DXF,再自己渲染。效果不如商业方案,但数据不出内网。
我选了第三条。理由很朴素:图纸属于客户的商业资产,哪怕只多一次外传,很多工厂的 IT 都会直接否掉整个方案。
转换命令其实是现成的
# DWG -> DXF,供前端解析
dwg2dxf -o out.dxf in.dwg
# DWG -> SVG,直接当缩略图
dwg2SVG -o out.svg in.dwg
真正的麻烦不在命令,在二进制分发:Linux 和 Windows 的构建完全不同,一个包动辄十几兆。这类文件如果直接塞进代码仓库,会让每次镜像构建和增量发布都变慢——我后来把非当前平台的包从构建上下文里剔掉,镜像体积立刻回来了。
三、缩略图与查看器要用两条链路
最容易踩的坑是把这两件事合并:列表页要的是"一眼能不能认出这张图",详情页要的是"能不能放大看标注"。前者对清晰度要求低,后者对结构要求高。
- 缩略图走 SVG/PNG,转换完立刻存下来,之后永远读缓存。一张图纸只转一次。
- 详情走 DXF → Canvas,需要图层、线型、文字,体积大,按需加载。
四、一定要异步,并且要给超时
转换耗时完全不可预测:几百 KB 的简单零件图几十毫秒,几十兆的装配图能跑到几分钟,还可能直接把进程耗死。放在请求里同步做,等于给自己埋一个随机超时。
做法是丢进队列,接口立刻返回任务 ID:
@task(bind=True, time_limit=120, soft_time_limit=100)
def convert_preview(self, drawing_id: str):
src = fetch_path(drawing_id)
with tempfile.TemporaryDirectory() as tmp:
out = os.path.join(tmp, "preview.svg")
run(["dwg2SVG", "-o", out, src], timeout=90, check=True)
store_preview(drawing_id, out)
三个细节缺一不可:time_limit、子进程的 timeout、以及独立的临时目录。少了任意一个,异常输入都可能留下僵尸进程或者半截文件。
安全上还有一条:永远不要用 shell=True。文件名来自用户上传,一个空格加个分号就能变成命令注入。参数一律用列表传。
五、失败要降级,但必须让人看见
DWG 的版本很多,老到 R14、新到 2018 之后的压缩格式,开源转换器不一定都吃得下。这时候最坏的设计是"静默返回空白":用户以为图纸是空的。
我的处理是给每种失败一个明确的出口:
| 情况 | 前端表现 |
|---|---|
| 转换成功 | 显示预览 + 可切换原始文件下载 |
| 格式不支持 | 明确提示"该版本暂不支持预览,请下载查看" |
| 转换超时 | 提示"文件较大,预览生成中",允许重试 |
| 转换器缺失 | 上传阶段就拦下来,不进入业务流 |
最后一行是我后来补的:把能力探测提前到上传入口。上传时先用一个极小的探针文件试一次转换器是否可用,不可用就直接拒绝,而不是让用户传到一半、等到详情页才发现打不开。
六、三维那条线,量力而行
STEP 的预览靠 OpenCascade 一类的几何内核转成网格,再交给 three.js。技术上可行,代价是依赖体积和首次加载时间都很难看,而且对装配体这种上千个零件的情况,浏览器端很容易卡死。
我目前的取舍是:三维只做"能转就转,转不动就退回二维缩略图"。不追求在网页里做完整的三维审图,那是一个专门的软件该干的事。
七、回头看,值得坚持的三条
- 图纸不离开自己的服务器。这一条决定了整个技术选型。
- 转换全部异步化,并且在三个层面都设超时。
- 失败必须有明确出口,绝不静默降级成空白页面。
至于转换质量,开源方案确实到不了商业 SDK 的水平。但对"看一眼是不是这张图"这个需求来说,够用了。