4. 开发环境与工具链搭建

DICOMweb 云影像平台同时涉及医学影像协议、Web 服务、数据库存储和前端交互,任何一环版本不匹配都会在联调阶段放大成难以定位的问题。因此本章的目标不是“把软件装上”,而是搭建一套可复现、可验证、可协作的本地开发环境:语言运行时、Web 框架、数据库、DICOM 测试数据、API 调试工具和版本控制六者版本固定、彼此连通,并能用一条命令或一个脚本重建。

一、语言与 Web 框架选型

DICOMweb 的核心是 HTTP 之上的 DICOM 语义,服务端需要处理 multipart/related 请求体、解析 DICOM 标签、生成 JSON 元数据,因此语言生态中是否有成熟的 DICOM 库是关键判断依据。以 Python 为例,pydicom 负责 DICOM 文件与数据集解析,pynetdicom 可辅助验证 DIMSE 侧行为,Web 框架选择 FastAPI,原因是它原生支持异步、自动生成 OpenAPI 文档,便于对照 DICOMweb 的 RESTful 接口逐条验证。

建议使用独立虚拟环境隔离依赖,并锁定版本:

python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate
pip install "fastapi==0.115.*" "uvicorn[standard]==0.32.*" \
            "pydicom==3.0.*" "sqlalchemy==2.0.*" "psycopg[binary]==3.2.*"
pip freeze > requirements.txt

这里把 requirements.txt 视为环境的一部分而非附属产物:团队成员执行 pip install -r requirements.txt 后应得到一致的依赖树。若使用 Node.js 承担前端或 BFF 层,则用 package.json 配合 package-lock.json 达到同样效果。

二、数据库与对象存储

平台的数据分两类:结构化元数据(患者、检查、序列、SOP 实例的层级关系与查询条件)和二进制影像(DICOM 文件或帧数据)。元数据适合放入关系型数据库,本地开发推荐 PostgreSQL,用 Docker 启动可避免污染宿主机:

docker run -d --name dw-pg \
  -e POSTGRES_PASSWORD=devpass \
  -e POSTGRES_DB=dicomweb \
  -p 5432:5432 postgres:16

影像文件本身不建议直接塞进数据库大字段,本地可用 MinIO 模拟 S3 兼容对象存储,键名按 studies/{studyUID}/series/{seriesUID}/instances/{sopUID}.dcm 组织,这样 WADO-RS 取回时可直接由 UID 拼出对象路径。数据库连接串通过环境变量注入,例如 DATABASE_URL=postgresql+psycopg://postgres:devpass@localhost:5432/dicomweb,避免硬编码进代码。

三、DICOM 测试数据准备

没有真实数据的平台无法验证。公开测试集如 pydicom 自带的 CT/MR 样例、TCIA 的公开数据集都可使用,但更可控的做法是自行构造覆盖关键场景的最小数据集:一个 Study 含两个 Series,其中一个 Series 有 3 个 Instance,另一个有 1 个,并包含不同 Transfer Syntax(如 Implicit VR Little Endian 与 Explicit VR Little Endian)。这样在验证 QIDO-RS 的 SeriesInstanceUID 过滤、WADO-RS 的 multipart/related 响应时才有区分度。

可用脚本批量生成并写入数据库索引,同时保留原始文件到对象存储,形成“文件 + 索引”双写。测试数据应纳入版本控制或单独的数据仓库,并记录每个文件的 SOPInstanceUID,便于断言。

四、API 调试与版本控制

DICOMweb 的请求头(Accept: application/dicom+json、multipart/related; type="application/dicom")和查询参数较多,建议用 Postman 或 Insomnia 建立集合,按 QIDO-RS、WADO-RS、STOW-RS 分组保存示例请求,并配合 FastAPI 自动生成的 /docs 交叉验证。命令行侧可用 curl 快速回归:

curl -H "Accept: application/dicom+json" \
  "http://localhost:8000/studies?PatientName=TEST^PATIENT"

版本控制方面,代码、配置模板、数据库迁移脚本、测试数据清单都应进入 Git;.gitignore 需排除 .venv/、*.dcm 大文件、本地数据库卷和密钥文件。分支策略可采用 main 保护 + 功能分支,提交信息关联接口编号,便于回溯某次 DICOMweb 行为变更。

DICOMweb 本地开发环境工具链 开发机 / Docker 网络 Python 3.12 + venv pydicom / pynetdicom requirements.txt 锁定 FastAPI + Uvicorn QIDO / WADO / STOW 自动 OpenAPI 文档 PostgreSQL 16 元数据索引 Docker 容器 MinIO (S3 兼容) DICOM 文件存储 按 UID 组织路径 DICOM 测试数据 1 Study / 2 Series 多 Transfer Syntax Postman / curl 接口集合与回归 Accept 头验证 Git 版本控制 代码 / 迁移 / 数据清单 环境变量注入连接串 · 依赖版本锁定 · 测试数据可重建

五、环境验证闭环

搭建完成后必须做一次端到端验证,而不是逐个组件“看起来正常”。建议按以下顺序执行并记录结果:启动 PostgreSQL 与 MinIO 容器,确认端口可连;运行数据库迁移脚本建表;执行测试数据导入脚本,检查数据库中出现 1 条 Study、2 条 Series、4 条 Instance 记录,对象存储中出现 4 个 .dcm 对象;启动 FastAPI 服务,访问 /docs 确认接口已注册;用 curl 发起 QIDO-RS 查询,期望返回 JSON 数组且 0020000D(StudyInstanceUID)与导入值一致;再发起 WADO-RS 请求,检查响应 Content-Type 为 multipart/related; type="application/dicom",且解析出的 SOPInstanceUID 与请求一致。

若 QIDO-RS 返回空数组,优先检查数据库索引是否写入、查询参数是否被 URL 编码、以及 PatientName 是否按 DICOM 的 Family^Given 格式传入,而不是先怀疑框架。

把上述步骤写成 scripts/bootstrap.sh 与 scripts/verify.sh,新成员克隆仓库后执行两条脚本即可得到可工作的环境。这一步的投入会在后续接口联调、回归测试和多人协作中持续回收,也是云影像平台工程化程度的第一道分水岭。