2026-05-03-23-22-10 修复阅览切换和下载触发
This commit is contained in:
55
工程分析/实现方案-2026-05-03-23-22-10.md
Normal file
55
工程分析/实现方案-2026-05-03-23-22-10.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# 实现方案
|
||||
|
||||
开始时间:2026-05-03-23-22-10
|
||||
|
||||
## 本次方案路径
|
||||
|
||||
`工程分析/实现方案-2026-05-03-23-22-10.md`
|
||||
|
||||
## 实现目标
|
||||
|
||||
修复 DICOM 阅览切片/显示模式切换导致后端连接重置的问题,并降低 ZIP 下载误触发和 HTTP 文件加载警告。
|
||||
|
||||
## 涉及文件
|
||||
|
||||
- `web_backend.py`
|
||||
- `WebSite/src/App.tsx`
|
||||
- `工程分析/经验记录.md`
|
||||
|
||||
## 执行步骤
|
||||
|
||||
1. 后端增加 DICOM 体数据缓存:
|
||||
- 增加 `DICOM_VOLUME_CACHE` 和锁。
|
||||
- 基于 DICOM 目录路径、文件数量、最新修改时间生成签名。
|
||||
- `/api/library/reformat-preview` 复用缓存体数据,避免每次切片/窗位变化都重新读取完整 DICOM。
|
||||
- 控制缓存规模,避免多个大体数据长期驻留。
|
||||
2. 后端下载容错:
|
||||
- `send_file` 捕获 `BrokenPipeError`、`ConnectionResetError`、`ConnectionAbortedError`,避免客户端中断下载时污染日志或影响服务。
|
||||
3. 前端 DICOM 阅览请求防抖:
|
||||
- 增加 `debouncedViewerSliceIndex`。
|
||||
- 切片滑杆变化后延迟短时间再请求后端,减少快速拖动时的请求数量。
|
||||
- 显示模式或平面切换仍可即时重置到中间切片,但实际请求走防抖后的切片索引。
|
||||
4. 前端 ZIP 下载防重复:
|
||||
- 增加已下载 ZIP job id 记录,确保同一个 ZIP job 自动下载只触发一次。
|
||||
5. 前端 ZIP 下载方式调整:
|
||||
- 对后端文件路径优先使用 `fetch` 获取 blob,再使用本地 `blob:` URL 触发下载。
|
||||
- 如 blob 下载失败,回退到原有 `/api/file` URL 方式,并提示用户。
|
||||
6. 执行测试方案。
|
||||
7. 更新 `工程分析/经验记录.md`。
|
||||
8. 提交并推送 Gitea,commit 信息使用 `2026-05-03-23-22-10 修复阅览切换和下载触发`。
|
||||
9. 重新部署到 `http://192.168.3.11:3005/`。
|
||||
|
||||
## 回滚思路
|
||||
|
||||
若缓存或 blob 下载出现问题,可回滚本次 `web_backend.py` 和 `WebSite/src/App.tsx` 修改,恢复直接读取体数据和直接 URL 下载方式。
|
||||
|
||||
## 风险控制
|
||||
|
||||
- 体数据缓存只影响阅览预览接口,不影响真实形变输出。
|
||||
- 缓存使用目录签名,影像库数据变化后会重新读取。
|
||||
- 删除影像库时同步清除 DICOM 文件缓存和体数据缓存。
|
||||
- 前端保留下载回退路径,避免 blob 下载失败后无法下载。
|
||||
|
||||
## 人工审核状态
|
||||
|
||||
用户已明确本次不需要人工二次确认,直接执行。
|
||||
78
工程分析/测试方案-2026-05-03-23-22-10.md
Normal file
78
工程分析/测试方案-2026-05-03-23-22-10.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# 测试方案
|
||||
|
||||
开始时间:2026-05-03-23-22-10
|
||||
|
||||
## 本次方案路径
|
||||
|
||||
`工程分析/测试方案-2026-05-03-23-22-10.md`
|
||||
|
||||
## 测试范围
|
||||
|
||||
- DICOM 阅览冠状位/矢状位请求是否稳定。
|
||||
- 切片滑杆快速变化是否不再导致后端被杀或连接重置。
|
||||
- 显示模式切换是否正常返回图片。
|
||||
- ZIP 下载 job 完成后是否只触发一次下载。
|
||||
- Python 语法、前端类型检查、构建是否通过。
|
||||
- 重新部署后服务是否可访问。
|
||||
|
||||
## 测试命令
|
||||
|
||||
Python 语法检查:
|
||||
|
||||
```bash
|
||||
python -m py_compile web_backend.py head_extension_app.py
|
||||
```
|
||||
|
||||
前端类型检查:
|
||||
|
||||
```bash
|
||||
cd WebSite
|
||||
npm run lint
|
||||
```
|
||||
|
||||
前端构建:
|
||||
|
||||
```bash
|
||||
cd WebSite
|
||||
npm run build
|
||||
```
|
||||
|
||||
后端阅览接口压力抽测:
|
||||
|
||||
```bash
|
||||
for i in 0 64 128 256 384 511; do
|
||||
curl -s "http://127.0.0.1:8787/api/library/reformat-preview?id=demo_ori_head_ct&plane=coronal&index=$i&window=bone" >/dev/null
|
||||
done
|
||||
```
|
||||
|
||||
部署验证:
|
||||
|
||||
```bash
|
||||
curl -I --max-time 5 http://192.168.3.11:3005/
|
||||
curl -s --max-time 10 "http://127.0.0.1:8787/api/library/reformat-preview?id=demo_ori_head_ct&plane=coronal&index=511&window=bone"
|
||||
```
|
||||
|
||||
## 手工验证点
|
||||
|
||||
- 打开数据影像库,进入 DICOM 阅览。
|
||||
- 拖动切片滑杆,图像更新且控制台不再出现 `ERR_CONNECTION_RESET`。
|
||||
- 切换显示模式,图像更新且后端服务保持在线。
|
||||
- 如有 ZIP 打包下载任务,完成后只自动下载一次。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- 后端不再因为阅览切片/窗位切换被 `Killed`。
|
||||
- `reformat-preview` 连续请求正常返回 JSON。
|
||||
- `npm run lint` 通过。
|
||||
- `npm run build` 通过。
|
||||
- `python -m py_compile web_backend.py head_extension_app.py` 通过。
|
||||
- Gitea commit/push 完成。
|
||||
- 重新部署后 `http://192.168.3.11:3005/` 返回 `200 OK`。
|
||||
|
||||
## 残余风险
|
||||
|
||||
- 纯 HTTP 部署下,浏览器可能仍会对下载文件给出安全提示;本次通过 blob 下载和重复触发保护尽量降低该提示出现概率。彻底消除需要 HTTPS 部署。
|
||||
|
||||
## 人工审核状态
|
||||
|
||||
用户已明确本次不需要人工二次确认,直接执行。
|
||||
18
工程分析/经验记录.md
18
工程分析/经验记录.md
@@ -55,3 +55,21 @@ C. 解决问题方案
|
||||
D. 后续如何避免问题
|
||||
|
||||
已有后端能力应先通过前端入口复用,不重复实现打包逻辑。DICOM 阅览类预览需要使用缓存,避免每次切换切片或窗宽窗位都重复生成相同图像;新增缓存应继续放在现有 `_preview_cache` 下,避免污染仓库。
|
||||
|
||||
## 2026-05-03-23-22-10 修复阅览切换和下载触发
|
||||
|
||||
A. 具体问题
|
||||
|
||||
DICOM 阅览切片滑杆和显示模式切换时,浏览器出现 `ERR_CONNECTION_RESET`;同时 ZIP 文件下载可能在其他 UI 操作期间再次触发,并出现 HTTP 文件加载安全提示。
|
||||
|
||||
B. 产生问题原因
|
||||
|
||||
阅览重建接口每次请求都重新读取整套 DICOM 体数据,切片滑杆快速拖动和显示模式切换会并发触发多个重建请求。前端 AbortController 只能取消浏览器等待,不能停止后端已经开始的 DICOM 读取,容易造成内存压力并导致后端被系统终止。ZIP 下载通过直接访问后端 `/api/file` URL 触发,且缺少已完成 ZIP job 的一次性下载保护。
|
||||
|
||||
C. 解决问题方案
|
||||
|
||||
后端为 DICOM 体数据增加基于目录签名的内存缓存,并限制缓存数量;阅览接口复用缓存体数据生成不同平面、切片和窗宽窗位的 PNG。前端为阅览切片请求增加防抖,减少滑杆拖动时的请求数量。ZIP 下载增加已下载 job id 记录,并优先使用 fetch blob 转本地 `blob:` URL 触发下载,失败时再回退到直接 URL。
|
||||
|
||||
D. 后续如何避免问题
|
||||
|
||||
涉及整套 DICOM 体数据读取的接口必须考虑缓存、并发和请求节流,不能把滑杆这类高频 UI 操作直接绑定到重型后端计算。自动下载类逻辑必须记录已处理 job,避免同一个完成状态在后续渲染或轮询中重复触发。
|
||||
|
||||
55
工程分析/需求分析-2026-05-03-23-22-10.md
Normal file
55
工程分析/需求分析-2026-05-03-23-22-10.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# 需求分析
|
||||
|
||||
开始时间:2026-05-03-23-22-10
|
||||
|
||||
## 原始需求
|
||||
|
||||
用户要求严格使用代码编纂工作流,并在最开始确认整体流程。本次需求分析、实现方案、测试方案和执行修改均不需要用户二次人工确认。
|
||||
|
||||
需要修复两个问题:
|
||||
|
||||
1. 点击 DICOM 阅览中的切片滚动条时出现与 ZIP 文件相关的浏览器警告:`The file at ...head_ct_morph_selected_54ed40feeb63.zip was loaded over an insecure connection. This file should be served over HTTPS.`
|
||||
2. 切换 DICOM 阅览显示模式时出现请求失败:`GET /api/library/reformat-preview ... net::ERR_CONNECTION_RESET`。
|
||||
|
||||
## 目标
|
||||
|
||||
- DICOM 阅览切片滚动和显示模式切换不再导致后端连接重置。
|
||||
- 降低切片滑杆快速拖动时的请求风暴和后端内存压力。
|
||||
- ZIP 下载完成后只触发一次下载,避免和其他 UI 操作交织造成误触发。
|
||||
- 尽量避免通过直接加载 ZIP URL 的方式触发浏览器 insecure file 警告。
|
||||
|
||||
## 影响范围
|
||||
|
||||
- `web_backend.py`
|
||||
- DICOM 阅览重建预览接口。
|
||||
- DICOM 体数据读取和缓存策略。
|
||||
- 文件下载响应的连接中断容错。
|
||||
- `WebSite/src/App.tsx`
|
||||
- DICOM 阅览请求节流/防抖。
|
||||
- ZIP 下载触发逻辑。
|
||||
- 已完成 ZIP job 的重复下载保护。
|
||||
- `工程分析/经验记录.md`
|
||||
|
||||
## 当前定位
|
||||
|
||||
- 后端日志显示 `python ../web_backend.py` 被系统 `Killed`,符合快速并发读取整套 DICOM 体数据导致内存压力过大的表现。
|
||||
- 当前 `/api/library/reformat-preview` 每次请求都会调用 `load_dicom_volume(item["dicomPath"])`,快速拖动滑杆或切换窗位会并发生成多个请求。
|
||||
- 前端阅览 effect 在 `viewerSliceIndex`、`viewerWindow` 等状态变化时立即发请求;AbortController 只中断浏览器端等待,不能中止后端已经开始的体数据读取。
|
||||
- ZIP 下载目前通过临时 `<a>` 直接访问后端 `/api/file?path=...zip`,浏览器可能显示 HTTP 文件下载安全警告;同时需要防止同一个 ZIP job 多次自动触发下载。
|
||||
|
||||
## 约束
|
||||
|
||||
- 不需要用户二次确认,可以直接执行修改。
|
||||
- 不改变真实 DICOM 形变算法。
|
||||
- 不引入大型前端 DICOM 阅片库。
|
||||
- 不把运行缓存图片、ZIP、DICOM 或构建产物提交到仓库。
|
||||
|
||||
## 风险点
|
||||
|
||||
- 体数据内存缓存会占用一定内存,需要按影像库目录签名复用并限制缓存规模。
|
||||
- Blob 下载大 ZIP 会占用浏览器内存;本次优先用于减少直接 URL 加载警告,仍需关注超大 ZIP 的浏览器表现。
|
||||
- 浏览器对 HTTP 下载的安全提示无法在纯 HTTP 部署下彻底消除;如果必须完全消除,需要 HTTPS 部署。
|
||||
|
||||
## 待确认事项
|
||||
|
||||
用户已明确本次不需要二次人工确认,因此本次文档写完后直接执行实现和测试。
|
||||
Reference in New Issue
Block a user