1. 程式人生 > 其它 >DICOM-SCP,可以直接使用的SCP(.net framework 4.5)控制檯接收端

DICOM-SCP,可以直接使用的SCP(.net framework 4.5)控制檯接收端



此程式引用的是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);
        }

    }
}
<?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>