C-STORE
约 605 字大约 2 分钟
PACSDICOMfo-dicomC-STORE
2026-03-20
C-STORE 既可能出现在“把影像上传到 PACS”的场景,也可能出现在“PACS 把影像推送到本地接收器”的场景。关键是先分清当前谁是 SCU,谁是 SCP。
1. SCU 与 SCP
SCU
Service Class User,发起存储请求的一方。
SCP
Service Class Provider,接收并保存影像的一方。
在不同场景中角色会变化:
- 上传到 PACS 时:本地程序通常是 SCU,PACS 是 SCP。
- 从 PACS 检索影像时:PACS 往往变成 SCU,本地接收器变成 SCP。
2. 上传请求:作为 SCU
构建请求
var request = new DicomCStoreRequest(dicomFilePath);处理响应
request.OnCStoreRequestResponseReceived += (req, resp) =>
{
Console.WriteLine($"C-STORE response received, Status: {resp.Status}");
};发送请求
var client = new DicomClient(pacsIp, pacsPort, false, localAet, remoteAet);
await client.AddRequestAsync(request);
await client.SendAsync();3. 下载接收:作为 SCP
本地接收端通常要先启动一个 C-STORE SCP 服务:
var server = DicomServer.Create<PacsCStoreSCP>(port: 104);
// 使用完成后关闭
server.Dispose();这里只是启动入口,真正关键的是 PacsCStoreSCP 这个类本身需要实现对应接口,常见包括:
DicomServiceIDicomServiceProviderIDicomCStoreProvider
4. 一个接收器实现的核心点
接收器通常需要处理下面这些环节:
- 接收关联请求。
- 协商 Presentation Context。
- 接收 C-STORE 请求并保存文件。
- 返回响应状态。
- 处理异常和连接关闭。
典型的 OnCStoreRequest 思路大致如下:
public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request)
{
var dicomFile = request.File;
var savePath = $"./Dicom/{dicomFile.FileMetaInfo.MediaStorageSOPInstanceUID.UID}.dcm";
Directory.CreateDirectory(Path.GetDirectoryName(savePath) ?? string.Empty);
dicomFile.Save(savePath);
return new DicomCStoreResponse(request, DicomStatus.Success);
}5. 使用建议
- 如果是做 C-MOVE 接收端,先确认本地 SCP 服务已经起来,再发 MOVE 请求。
- 处理影像接收时,文件命名、目录组织和异常日志要尽早定下来,不然后续排查很痛苦。
- 上传和下载都依赖同一套 AE Title、网络和协商前提,所以出现问题时先回头看 2.AE Title 与节点配置、5.DicomClient 和 6.C-ECHO。
6. 在 Storage Commitment 里的位置
如果你要把上传流程做完整,可以继续看 14.Storage Commitment 流程总览 和 15.发送影像并发起存储承诺.md。C-STORE 负责把对象送达,真正的“承诺完成”还要依赖后续的 N-ACTION 和 N-EVENT-REPORT。