สถาบันการดูแลสุขภาพต้องการโซลูชั่นอัตโนมัติมากขึ้นเพื่อลบการระบุข้อมูลภาพทางการแพทย์ ในคู่มือนี้คุณจะเรียนรู้วิธีการสร้างบริการไมโครซอฟต์แวร์การอ้างอิงของ DICOM ใน ASP.NET Core** ซึ่งจะรับไฟล์ DIKOM ผ่าน HTTP, anonimizes พวกเขาโดยใช้โปรไฟล์ที่กําหนดเองและคืนผลลัพธ์ที่ล้มเหลว ในที่สุดคุณจะมีสถาปัตยกรรมบริการพร้อมการผลิตพร้อมรหัสแหล่งตัวอย่าง

ตารางเนื้อหา

สถาปัตยกรรม Overview

ไมโครเซิร์ฟเวอร์ปฏิบัติตามโครงสร้างชั้นที่มีการแยกที่ชัดเจนของความกังวล ชั้น API จัดการคําขอและตอบสนอง HTTP ผ่านตัวควบคุมหลัก ASP.NET ชั้นบริการประกอบด้วยโลโก้ธุรกิจโดยใช้ Aspose.Medical Anonymizer ชั้นการกําหนดค่าจัดการการตั้งค่าโปรไฟล์และตัวเลือกการใช้งาน ส่วนประกอบทางเลือกรวมถึงการจัดเก็บข้อมูลสําหรับการเข้าสู่ระบบและสแกนสําหรับการประมวลผลแพทช์

อาคารนี้ช่วยให้การสแกนแนวนอนการทดสอบง่ายและการบูรณาการได้อย่างง่ายดายกับระบบข้อมูลโรงพยาบาลและเซิร์ฟเวอร์ PACS

การตั้งค่าโครงการ

เริ่มต้นโดยการสร้างโครงการ API Web Core ASP.NET ใหม่และติดตั้งแพคเกจที่ต้องการ:

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();

การดําเนินงานของ Layer Service

สร้างอินเทอร์เฟซและการประยุกต์ใช้สําหรับบริการ匿名:

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

การรับรองการดําเนินการ ใช้ tokens 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...
}

การประมวลผลคําขอ quuing สําหรับแพทช์ขนาดใหญ่มากโดยใช้อัตราข้อความเช่น RabbitMQ หรือ Azure Service Bus เพื่อจัดการความเร็วในการโหลดโดยไม่ต้องเอาชนะบริการ

ข้อสรุป

ตอนนี้คุณมีแผนภาพที่สมบูรณ์สําหรับการสร้าง DICOM anonymization microservice ใน ASP.NET Core บริการนี้ยอมรับไฟล์ DICO via HTTP ใช้โปรไฟล์ anonymisation ที่กําหนดเองโดยใช้ Aspose.Medical และส่งไฟล์ที่ไม่ได้ระบุพร้อมสําหรับการวิจัยหรือแบ่งปัน

ข้อตกลงหลักรวมถึงการใช้โครงสร้างชั้นสําหรับการบํารุงรักษาการนําไปใช้โปรไฟล์ที่กําหนดเองเพื่อความยืดหยุ่นการรักษาบริการด้วยการรับรองและการเข้ารหัสและการเพิ่มประสิทธิภาพในการประมวลผลร่วมกัน

สําหรับรหัสแหล่งข้อมูลที่สมบูรณ์และตัวอย่างเพิ่มเติมเยี่ยมชม Aspose.Documentationทางการแพทย์เพื่อทดลองไฟ รับใบอนุญาตชั่วคราวฟร.

More in this category