تحتاج المنظمات الصحية بشكل متزايد إلى حلول آلية لتفكيك بيانات الصورة الطبية.في هذا الدليل، سوف تتعلم كيفية إنشاء DICOM anonimization microservice في ASP.NET Core التي تتلقى ملفات ديكوم عبر HTTP، وتجسدها باستخدام الملفات المثبتة، وإرجاع النتائج غير المحددة.

جدول المحتوى

نظرة عامة على المعمارية

يتبع microservice بنية طبقة مع انفصال واضح عن المخاوف.تتعامل الطبقة API مع طلبات HTTP والإجابات من خلال التحكمات الأساسية ASP.NET.يحتوي الطبق الخدمة على المنطق التجاري باستخدام Aspose.Medical Anonymizer.يتحكم الطبقات التكوينية في إعدادات الملف الشخصي وخيارات التطبيق.تشمل المكونات الاختيارية التخزين للتسجيل والتحويل لمعالجة المجموعات.

يتيح هذا الهندسة المعمارية التوسع الأفقي والتجربة السهلة والتكامل السهل مع أنظمة المعلومات في المستشفيات وخوادم PACS.

إعداد المشروع

ابدأ بإنشاء مشروع جديد لـ ASP.NET Core Web API وتثبيت الحزمة المطلوبة:

dotnet new webapi -n DicomAnonymizationService
cd DicomAnonymizationService
dotnet add package Aspose.Medical

إعداد المشروع لتحميل الملفات الكبيرة في Program.cs:

var builder = WebApplication.CreateBuilder(args);

// Configure for large DICOM files
builder.WebHost.ConfigureKestrel(options =>
{
    options.Limits.MaxRequestBodySize = 500_000_000; // 500MB
});

builder.Services.Configure<FormOptions>(options =>
{
    options.MultipartBodyLengthLimit = 500_000_000;
});

// Register services
builder.Services.AddScoped<IDicomAnonymizationService, DicomAnonymizationService>();
builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();
app.Run();

تنفيذ طبقة الخدمة

إنشاء واجهة وتنفيذ لخدمة المجهول:

using Aspose.Medical.Dicom;
using Aspose.Medical.Dicom.Anonymization;

public interface IDicomAnonymizationService
{
    Task<byte[]> AnonymizeAsync(Stream inputStream, string? profileName = null);
    Task<byte[]> AnonymizeAsync(byte[] inputBytes, string? profileName = null);
}

public class DicomAnonymizationService : IDicomAnonymizationService
{
    private readonly ILogger<DicomAnonymizationService> _logger;
    private readonly Dictionary<string, ConfidentialityProfileOptions> _profiles;

    public DicomAnonymizationService(ILogger<DicomAnonymizationService> logger)
    {
        _logger = logger;
        _profiles = new Dictionary<string, ConfidentialityProfileOptions>
        {
            ["basic"] = ConfidentialityProfileOptions.BasicProfile,
            ["research"] = ConfidentialityProfileOptions.BasicProfile | 
                          ConfidentialityProfileOptions.RetainPatientChars,
            ["internal"] = ConfidentialityProfileOptions.RetainUIDs | 
                          ConfidentialityProfileOptions.RetainDeviceIdent,
            ["clean"] = ConfidentialityProfileOptions.CleanGraph | 
                       ConfidentialityProfileOptions.CleanDesc
        };
    }

    public async Task<byte[]> AnonymizeAsync(Stream inputStream, string? profileName = null)
    {
        using var memoryStream = new MemoryStream();
        await inputStream.CopyToAsync(memoryStream);
        return await AnonymizeAsync(memoryStream.ToArray(), profileName);
    }

    public Task<byte[]> AnonymizeAsync(byte[] inputBytes, string? profileName = null)
    {
        return Task.Run(() =>
        {
            // Create anonymizer with selected profile
            Anonymizer anonymizer = CreateAnonymizer(profileName);

            // Load DICOM from bytes
            using var inputStream = new MemoryStream(inputBytes);
            DicomFile dcm = DicomFile.Open(inputStream);

            // Anonymize
            DicomFile anonymizedDcm = anonymizer.Anonymize(dcm);

            // Write to output stream
            using var outputStream = new MemoryStream();
            anonymizedDcm.Save(outputStream);

            _logger.LogInformation("Anonymized DICOM file using profile: {Profile}", 
                profileName ?? "default");

            return outputStream.ToArray();
        });
    }

    private Anonymizer CreateAnonymizer(string? profileName)
    {
        if (string.IsNullOrEmpty(profileName) || !_profiles.ContainsKey(profileName.ToLower()))
        {
            return new Anonymizer();
        }

        var options = _profiles[profileName.ToLower()];
        var profile = ConfidentialityProfile.CreateDefault(options);
        return new Anonymizer(profile);
    }
}

بناء التحكم API

إنشاء جهاز التحكم الذي يتعامل مع تحميل الملفات وإرجاع ملفات DICOM المجهولة:

using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class AnonymizeController : ControllerBase
{
    private readonly IDicomAnonymizationService _anonymizationService;
    private readonly ILogger<AnonymizeController> _logger;

    public AnonymizeController(
        IDicomAnonymizationService anonymizationService,
        ILogger<AnonymizeController> logger)
    {
        _anonymizationService = anonymizationService;
        _logger = logger;
    }

    /// <summary>
    /// Anonymize a single DICOM file
    /// </summary>
    [HttpPost]
    [RequestSizeLimit(500_000_000)]
    public async Task<IActionResult> AnonymizeFile(
        IFormFile file,
        [FromQuery] string? profile = null)
    {
        if (file == null || file.Length == 0)
        {
            return BadRequest("No file uploaded");
        }

        try
        {
            _logger.LogInformation("Processing file: {FileName}, Size: {Size}", 
                file.FileName, file.Length);

            using var stream = file.OpenReadStream();
            byte[] anonymizedBytes = await _anonymizationService.AnonymizeAsync(stream, profile);

            string outputFileName = $"anonymized_{file.FileName}";
            return File(anonymizedBytes, "application/dicom", outputFileName);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error anonymizing file: {FileName}", file.FileName);
            return StatusCode(500, $"Anonymization failed: {ex.Message}");
        }
    }

    /// <summary>
    /// Anonymize DICOM data from request body
    /// </summary>
    [HttpPost("stream")]
    [RequestSizeLimit(500_000_000)]
    public async Task<IActionResult> AnonymizeStream([FromQuery] string? profile = null)
    {
        try
        {
            byte[] anonymizedBytes = await _anonymizationService.AnonymizeAsync(
                Request.Body, profile);

            return File(anonymizedBytes, "application/dicom", "anonymized.dcm");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error anonymizing stream");
            return StatusCode(500, $"Anonymization failed: {ex.Message}");
        }
    }

    /// <summary>
    /// List available anonymization profiles
    /// </summary>
    [HttpGet("profiles")]
    public IActionResult GetProfiles()
    {
        var profiles = new[]
        {
            new { name = "basic", description = "Standard anonymization removing most identifiers" },
            new { name = "research", description = "Retains patient characteristics for research" },
            new { name = "internal", description = "Retains UIDs for internal tracking" },
            new { name = "clean", description = "Removes burned-in graphics and descriptions" }
        };

        return Ok(profiles);
    }
}

ملفات تعريفية قابلة للتكوين

تسمح للملفات بتكوينها من خلال appsettings.json:

{
  "AnonymizationProfiles": {
    "default": "basic",
    "profiles": {
      "basic": ["BasicProfile"],
      "research": ["BasicProfile", "RetainPatientChars"],
      "internal": ["RetainUIDs", "RetainDeviceIdent"],
      "clean": ["CleanGraph", "CleanDesc"],
      "maximum": ["BasicProfile", "CleanGraph", "CleanDesc"]
    }
  }
}

قم بإنشاء فئة تكوين وتحديث الخدمة للقراءة من الإعدادات:

public class AnonymizationProfileOptions
{
    public string Default { get; set; } = "basic";
    public Dictionary<string, string[]> Profiles { get; set; } = new();
}

// In Program.cs
builder.Services.Configure<AnonymizationProfileOptions>(
    builder.Configuration.GetSection("AnonymizationProfiles"));

ملاحظات أمنية {#أمن الاعتبارات}

عند نشر هذه الخدمة، تنفيذ هذه التدابير الأمنية.

إمكانية HTTPS لضمان تشفير جميع الاتصالات أثناء النقل.إعداد TLS 1.2 أو أعلى وإعادة توجيه http إلى http.

تطبيق التحقق باستخدام رموز JWT أو مفاتيح API للحد من الوصول إلى العملاء المعتمدين:

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class AnonymizeController : ControllerBase
{
    // Controller code...
}

تجنب تخزين الملفات الأصلية غير المشفرة على القرص.معالجة ملفات في الذاكرة عندما يكون ذلك ممكنا، وإذا كان هناك حاجة لتخزينة مؤقتة، استخدم حجم مشفر.

إمكانية تسجيل الدخول إلى التدقيق لتتبع جميع عمليات الهوية بما في ذلك من طلبها وعندما:

_logger.LogInformation(
    "Anonymization completed - User: {User}, Profile: {Profile}, FileSize: {Size}",
    User.Identity?.Name, profile, file.Length);

تحسين الأداء

العديد من التقنيات يمكن أن تحسن الأداء في سيناريوهات عالية السرعة.

استخدام المجهول في الموقع عندما لا تحتاج إلى الاحتفاظ بالبيانات الأصلية في الذاكرة:

anonymizer.AnonymizeInPlace(dcm);

إمكانية المعالجة الموازية للعمليات المجموعة:

[HttpPost("batch")]
public async Task<IActionResult> AnonymizeBatch(List<IFormFile> files)
{
    var results = await Parallel.ForEachAsync(
        files,
        new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
        async (file, ct) =>
        {
            using var stream = file.OpenReadStream();
            return await _anonymizationService.AnonymizeAsync(stream);
        });

    // Return results...
}

تطبيق طلب الاستدعاء للقطع الكبيرة جدا باستخدام قطعة الرسائل مثل RabbitMQ أو Azure Service Bus للتعامل مع شرائح الشحن دون إزعاج الخدمة.

استنتاجات {# الاستنتاج}

لديك الآن نموذج كامل لبناء DICOM المجهول خدمة الميكروويف في ASP.NET Core. يوافق الخدمة على ملفات DIKOM من خلال HTTP، وتطبيق ملف تعريف الهوية قابلة للتكوين باستخدام Aspose.Medical، وإرجاع الملفات غير المعترف بها جاهزة للبحث أو المشاركة.

وتشمل المهام الرئيسية استخدام الهندسة المعمارية المسطحة للصيانة، وتنفيذ ملفات تعريف قابلة للتكوين لمرونة، وتأمين الخدمة مع التحقق والتشفير، وتحسين الأداء مع المعالجة الموازية.

للحصول على رمز المصدر الكامل والمزيد من الأمثلة، يرجى زيارة الوسوم - الوثائق الطبيةلتجربة النار، الحصول على ترخيص مؤقت مجاني.

More in this category