此程序引用的是Dicom.Core 4.0.8.0,也是最后一版支持部署在.net framework 4.5 或以下环境的。如需要部署在.net4.6.1以上的需要查看另一个文档。
1 using Dicom;
2 using Dicom.Log;
3 using Dicom.Network;
4 using Microsoft.Build.Framework;
5 using System;
6 using System.Collections.Generic;
7 using System.Configuration;
8 using System.IO;
9 using System.Linq;
10 using System.Text;
11 using System.Threading.Tasks;
12
13 namespace Store_SCP
14 {
15 class Program
16 {
17 private static readonly string _storagePath = ConfigurationManager.AppSettings["StoragePath"];
18
19 private static readonly int _port = int.Parse(ConfigurationManager.AppSettings["Port"]);
20
21 private static readonly string _calledAE = ConfigurationManager.AppSettings["CalledAE"];
22
23 private static void Main(string[] args)
24 {
25 // preload dictionary to prevent timeouts
26 var dict = DicomDictionary.Default;
27
28 // start DICOM server on port from command line argument or 11112
29 var port = _port;
30 Console.WriteLine($"正在端口上启动C-Store SCP服务器,端口:{port},LocalAE:{_calledAE}");
31
32 using (var server = DicomServer.Create<CStoreSCP>(port))
33 {
34 // end process
35 Console.WriteLine("Press <return> to end...");
36 Console.ReadLine();
37 }
38 }
39
40
41 private class CStoreSCP : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
42 {
43 private static readonly DicomTransferSyntax[] AcceptedTransferSyntaxes = new DicomTransferSyntax[]
44 {
45 DicomTransferSyntax.ExplicitVRLittleEndian,
46 DicomTransferSyntax.ExplicitVRBigEndian,
47 DicomTransferSyntax.ImplicitVRLittleEndian
48 };
49
50 private static readonly DicomTransferSyntax[] AcceptedImageTransferSyntaxes = new DicomTransferSyntax[]
51 {
52 // Lossless
53 DicomTransferSyntax.JPEGLSLossless,
54 DicomTransferSyntax.JPEG2000Lossless,
55 DicomTransferSyntax.JPEGProcess14SV1,
56 DicomTransferSyntax.JPEGProcess14,
57 DicomTransferSyntax.RLELossless,
58 // Lossy
59 DicomTransferSyntax.JPEGLSNearLossless,
60 DicomTransferSyntax.JPEG2000Lossy,
61 DicomTransferSyntax.JPEGProcess1,
62 DicomTransferSyntax.JPEGProcess2_4,
63 // Uncompressed
64 DicomTransferSyntax.ExplicitVRLittleEndian,
65 DicomTransferSyntax.ExplicitVRBigEndian,
66 DicomTransferSyntax.ImplicitVRLittleEndian
67 };
68
69 public CStoreSCP(INetworkStream stream, Encoding fallbackEncoding, Logger log)
70 : base(stream, fallbackEncoding, log)
71 {
72 }
73
74 public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
75 {
76 if (association.CalledAE != _calledAE)
77 {
78 return SendAssociationRejectAsync(
79 DicomRejectResult.Permanent,
80 DicomRejectSource.ServiceUser,
81 DicomRejectReason.CalledAENotRecognized);
82 }
83
84 foreach (var pc in association.PresentationContexts)
85 {
86 if (pc.AbstractSyntax == DicomUID.Verification) pc.AcceptTransferSyntaxes(AcceptedTransferSyntaxes);
87 else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None) pc.AcceptTransferSyntaxes(AcceptedImageTransferSyntaxes);
88 }
89
90 return SendAssociationAcceptAsync(association);
91 }
92
93 public Task OnReceiveAssociationReleaseRequestAsync()
94 {
95 return SendAssociationReleaseResponseAsync();
96 }
97
98 public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
99 {
100 }
101
102 public void OnConnectionClosed(Exception exception)
103 {
104 }
105
106 public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request)
107 {
108 try
109 {
110 var studyUid = request.Dataset.GetSingleValue<string>(DicomTag.StudyInstanceUID);
111 var instUid = request.SOPInstanceUID.UID;
112
113 var path = Path.GetFullPath(_storagePath);
114 path = Path.Combine(path, studyUid);
115
116 if (!Directory.Exists(path)) Directory.CreateDirectory(path);
117
118 path = Path.Combine(path, instUid) + ".dcm";
119
120 request.File.Save(path);
121
122 LoggerHelper.Instance().Info($"已成功将文件存入到{path}");
123 }
124 catch (Exception ex)
125 {
126
127 LoggerHelper.Instance().Info($"文件保存失败,失败原因:{ex.Message}");
128 }
129 return new DicomCStoreResponse(request, DicomStatus.Success);
130 }
131
132 public void OnCStoreRequestException(string tempFileName, Exception e)
133 {
134 // let library handle logging and error response
135 }
136
137 public DicomCEchoResponse OnCEchoRequest(DicomCEchoRequest request)
138 {
139 return new DicomCEchoResponse(request, DicomStatus.Success);
140 }
141 }
142 }
143
144 }
using System;
using System.Reflection;
using log4net;
using log4net.Config;
namespace Store_SCP
{
public class LoggerHelper
{
private static LoggerHelper _instance = null;
private static object _locker = new object();
private ILog _logger;
private LoggerHelper()
{
XmlConfigurator.Configure();
Type type =MethodBase.GetCurrentMethod().DeclaringType;
this._logger = LogManager.GetLogger(type);
}
public static LoggerHelper Instance()
{
if (_instance == null)
{
lock (_locker)
{
if (_instance == null)
{
_instance = new LoggerHelper();
}
}
}
return _instance;
}
public void Debug(object obj)
{
this._logger.Debug(obj);
}
public void Error(object obj)
{
this._logger.Error(obj);
}
public void Fatal(object obj)
{
this._logger.Fatal(obj);
}
public void Info(object obj)
{
this._logger.Info(obj);
}
public void Warn(object obj)
{
this._logger.Warn(obj);
}
public void Debug(object obj, Exception e)
{
this._logger.Debug(obj, e);
}
public void Error(object obj, Exception e)
{
this._logger.Error(obj, e);
}
public void Fatal(object obj, Exception e)
{
this._logger.Fatal(obj, e);
}
public void Info(object obj, Exception e)
{
this._logger.Info(obj, e);
}
public void Warn(object obj, Exception e)
{
this._logger.Warn(obj, e);
}
}
}
此是app.config文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
<file value="Logs/" />
<appendToFile value="true" />
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<rollingStyle value="Date"/>
<!--这是按日期产生文件夹-->
<datePattern value="yyyyMM\\yyyyMMdd'.txt'"/>
<!--是否只写到一个文件中-->
<staticLogFileName value="false"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>
<root>
<appender-ref ref="RollingFileAppender" />
<level value="DEBUG" />
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="StoragePath" value="MYDICOM/"/>
<add key="Port" value="11112"/>
<add key="CalledAE" value="STORESCP11112"/>
</appSettings>
</configuration>