实现了支持文件夹、ZIP压缩包的高级批量上传功能,具备以下特性:
~/qconline/dicom/{institutionId}/{date}/{fileId}.dcm
~/qconline/dicom/{institutionId}/{study_instance_uid}/{fileId}.dcm
优势: 同一个检查的所有文件都在同一个目录下,便于管理和访问
表: study_info
-- 添加批次ID字段
ALTER TABLE `study_info`
ADD COLUMN `batch_id` VARCHAR(50) NULL COMMENT '批次ID:同一批上传的影像共享同一个batch_id'
AFTER `parent_study_id`;
-- 添加索引
ALTER TABLE `study_info`
ADD INDEX `idx_batch_id` (`batch_id`);
字段说明:
batch_id: 批次ID,同一批上传的所有study共享同一个batch_idparent_study_id: 父检查ID,第一个study为null,其他study指向第一个study关联关系:
批次1: batch_id = "BATCH_1234567890"
├─ Study A (主study, parent_study_id = NULL)
├─ Study B (子study, parent_study_id = Study A的studyId)
└─ Study C (子study, parent_study_id = Study A的studyId)
路径: /src/main/java/com/zskk/qconline/modules/dicom/util/ArchiveUtil.java
功能:
路径: /src/main/java/com/zskk/qconline/modules/dicom/vo/BatchUploadVO.java
功能:
路径: /src/main/java/com/zskk/qconline/modules/dicom/service/DicomService.java
新增方法:
BatchUploadVO batchUploadAdvanced(MultipartFile[] files, String institutionId);
路径: /src/main/java/com/zskk/qconline/modules/dicom/service/impl/DicomServiceImpl.java
新增方法:
batchUploadAdvanced(): 高级批量上传主方法groupFilesByStudyInstanceUid(): 按study_instance_uid分组文件saveStudyFiles(): 保存文件到study_instance_uid目录核心逻辑:
路径: /src/main/java/com/zskk/qconline/modules/entity/StudyInfo.java
新增字段:
@TableField("batch_id")
private String batchId;
路径: /src/main/java/com/zskk/qconline/modules/dicom/controller/DicomController.java
新增接口:
POST /api/dicom/batch-upload-advanced
请求参数:
files: MultipartFile[](文件数组)institutionId: String(机构ID)返回结果:
{
"code": 200,
"message": "上传成功",
"data": {
"batchId": "BATCH_1234567890",
"totalFiles": 150,
"studyCount": 2,
"studies": [
{
"studyId": "STY1234567890",
"studyInstanceUid": "1.2.840.113619.2.55.3...",
"patientId": "P12345",
"patientName": "张三",
"modality": "CT",
"bodyPart": "胸部",
"fileCount": 100,
"isPrimary": true
},
{
"studyId": "STY1234567891",
"studyInstanceUid": "1.2.840.113619.2.55.3...",
"patientId": "P12345",
"patientName": "张三",
"modality": "MR",
"bodyPart": "颅脑",
"fileCount": 50,
"isPrimary": false
}
]
}
}
curl -X POST http://localhost:8080/api/dicom/batch-upload-advanced \
-F "files=@image.dcm" \
-F "institutionId=INST001"
curl -X POST http://localhost:8080/api/dicom/batch-upload-advanced \
-F "files=@study.zip" \
-F "institutionId=INST001"
curl -X POST http://localhost:8080/api/dicom/batch-upload-advanced \
-F "files=@image1.dcm" \
-F "files=@image2.dcm" \
-F "files=@image3.dcm" \
-F "institutionId=INST001"
压缩包解压时会使用系统临时目录:
# macOS/Linux
/tmp/dicom_upload_xxxxxxxx/
# Windows
C:\Users\{username}\AppData\Local\Temp\dicom_upload_xxxxxxxx\
private static final String DICOM_ROOT_PATH = System.getProperty("user.home") + "/qconline/dicom/";
# 连接到数据库
mysql -u root -p
# 选择数据库
use qconline;
# 执行SQL脚本
source /path/to/alter_study_info_add_batch_id.sql;
当上传的压缩包包含多个不同study_instance_uid的文件时:
为了兼容现有系统,保留了旧的上传接口:
/api/dicom/upload - 单文件上传(旧)/api/dicom/batch-upload - 批量上传(旧)/api/dicom/batch-upload-advanced - 高级批量上传(新)[INFO] 开始批量上传: institutionId=INST001, 文件数=1
[INFO] 批次ID: BATCH_1735189234567
[INFO] 检测到压缩包: study.zip
[INFO] 创建临时目录: /var/folders/.../dicom_upload_a1b2c3d4
[INFO] 开始解压文件: /var/folders/.../study.zip
[INFO] 解压完成,共解压 150 个文件
[INFO] 共收集到 150 个文件需要处理
[INFO] 识别到 2 个不同的study
[INFO] 处理study: studyInstanceUid=1.2.840..., 文件数=100
[INFO] 创建study目录: /Users/xxx/qconline/dicom/INST001/1.2.840.../
[INFO] 创建study记录: studyId=STY001, studyInstanceUid=1.2.840..., 文件数=100
[INFO] 处理study: studyInstanceUid=1.2.841..., 文件数=50
[INFO] 创建study目录: /Users/xxx/qconline/dicom/INST001/1.2.841.../
[INFO] 创建study记录: studyId=STY002, studyInstanceUid=1.2.841..., 文件数=50
[INFO] 批量上传完成: batchId=BATCH_1735189234567, 总文件数=150, study数=2
[INFO] 清理临时目录: /var/folders/.../dicom_upload_a1b2c3d4
使用Element Plus的el-upload组件,添加以下功能:
webkitdirectory属性)使用新的批量上传接口:
const formData = new FormData()
files.forEach(file => {
formData.append('files', file)
})
formData.append('institutionId', institutionId)
axios.post('/api/dicom/batch-upload-advanced', formData)
后端功能已全部实现,包括:
接下来需要修改前端上传组件以使用新接口。