← 返回笔记列表
2026-10-15 · 图形与文件处理

CAD 图纸在线预览:格式选型与转换链路

客户丢过来一个 DWG,问"能不能在网页里看一眼"。这个需求听起来像前端问题,实际上是文件格式问题——浏览器从来没有打算认识 CAD 图纸。

一、先认清格式

机械行业的图纸基本跑不出这几类,处理难度差别很大:

格式性质处理难度
PDF已经是版式文件低,浏览器/PDF.js 直接渲染
DXF文本结构的矢量图中,解析实体后自己画
DWGAutodesk 私有二进制高,必须经转换器
STEP / IGES三维 B-rep 实体高,需要几何内核
STL / 3MF三角网格低,three.js 直接加载

二维和三维是两条完全不同的管线,不要试图用一套代码吃掉。二维的目标是"看清标注",三维的目标是"看清形状",对精度的要求正好相反。

二、DWG 的三条路,以及为什么选本地转换

要让浏览器看到 DWG 内容,本质上只有三条路:

  1. 调用商业 SDK。ODA、Autodesk 都有现成方案,效果最好,成本和授权最重。
  2. 用云服务转换。上传后拿到图片或 PDF,省事,但图纸是客户的,出门这一步在制造业里过不去。
  3. 本地开源转换器。LibreDWG 这类项目能把 DWG 转成 DXF,再自己渲染。效果不如商业方案,但数据不出内网。

我选了第三条。理由很朴素:图纸属于客户的商业资产,哪怕只多一次外传,很多工厂的 IT 都会直接否掉整个方案。

转换命令其实是现成的

# DWG -> DXF,供前端解析
dwg2dxf -o out.dxf in.dwg

# DWG -> SVG,直接当缩略图
dwg2SVG -o out.svg in.dwg

真正的麻烦不在命令,在二进制分发:Linux 和 Windows 的构建完全不同,一个包动辄十几兆。这类文件如果直接塞进代码仓库,会让每次镜像构建和增量发布都变慢——我后来把非当前平台的包从构建上下文里剔掉,镜像体积立刻回来了。

三、缩略图与查看器要用两条链路

最容易踩的坑是把这两件事合并:列表页要的是"一眼能不能认出这张图",详情页要的是"能不能放大看标注"。前者对清晰度要求低,后者对结构要求高。

四、一定要异步,并且要给超时

转换耗时完全不可预测:几百 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。技术上可行,代价是依赖体积和首次加载时间都很难看,而且对装配体这种上千个零件的情况,浏览器端很容易卡死。

我目前的取舍是:三维只做"能转就转,转不动就退回二维缩略图"。不追求在网页里做完整的三维审图,那是一个专门的软件该干的事。

七、回头看,值得坚持的三条

  1. 图纸不离开自己的服务器。这一条决定了整个技术选型。
  2. 转换全部异步化,并且在三个层面都设超时。
  3. 失败必须有明确出口,绝不静默降级成空白页面。

至于转换质量,开源方案确实到不了商业 SDK 的水平。但对"看一眼是不是这张图"这个需求来说,够用了。