Organisasi penjagaan kesehatan semakin membutuhkan solusi otomatis untuk de-identifikasi data gambar medis.Dalam panduan ini, Anda akan belajar bagaimana untuk membangun sebuah DICOM anonimization microservice di ASP.NET Core yang menerima file DIKOM melalui HTTP, menganonimkan mereka menggunakan profil yang dapat dikonfigurasi, dan mengembalikan hasil yang tidak dikenal.

Jadual Konten

Perbedaan Arsitektur (Arkitektur)

The microservice mengikuti arsitektur lapisan dengan pemisahan yang jelas dari kebimbangan. Layer API menangani permintaan HTTP dan respons melalui pengendali ASP.NET Core. layer layanan berisi logika bisnis menggunakan Aspose.Medical Anonymizer. Lapisan konfigurasi mengelola pengaturan profil dan opsi aplikasi. Komponen pilihan termasuk penyimpanan untuk logging dan kuing untuk pemrosesan batch.

Arsitektur ini memungkinkan skala horizontal, pemeriksaan mudah, dan integrasi sederhana dengan sistem informasi rumah sakit dan server PACS.

Setting Up Project

Mulai dengan membuat proyek baru ASP.NET Core Web API dan menginstal paket yang diperlukan:

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

Mengkonfigurasi proyek untuk file besar upload di 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();

Mengimplementasikan Layer Service

Mencipta antara muka dan implementasi untuk layanan anonim:

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

Membangun API Controller

Mencipta controller yang mengendalikan upload file dan mengembalikan file DICOM yang anonim:

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

Profil yang dapat dikonfigurasikan

Memungkinkan profil untuk dikonfigurasi melalui appsettings.json:

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

Buat kelas konfigurasi dan update layanan untuk dibaca dari pengaturan:

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

Pertimbangan Keselamatan (Security Considerations)

Ketika mengimplementasikan layanan ini, melaksanakan langkah-langkah keamanan ini.

Mengaktifkan HTTPS untuk memastikan semua komunikasi disulitkan dalam transit. mengkonfigurasi TLS 1.2 atau lebih tinggi dan mengarahkan Http ke https.

Implementation authentication menggunakan token JWT atau kunci API untuk membatasi akses ke klien yang diberi izin:

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

Menghindari penyimpanan file asli yang tidak terenkripsi pada cakera.Proses file dalam memori kapan saja mungkin, dan jika simpanan sementara diperlukan, gunakan volume tersulit.

Mengizinkan pendaftaran audit untuk memantau semua operasi anonimitas termasuk siapa yang meminta mereka dan ketika:

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

Optimisasi Performa (Performance Optimization)

Beberapa teknik dapat meningkatkan kinerja untuk skenario kecepatan tinggi.

Menggunakan anonimitas di tempat ketika Anda tidak perlu menyimpan data asli dalam memori:

anonymizer.AnonymizeInPlace(dcm);

** Memungkinkan pemrosesan paralel** untuk operasi batch:

[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...
}

Implementasi permintaan kuing untuk batch yang sangat besar menggunakan kue pesan seperti RabbitMQ atau Azure Service Bus untuk menangani puncak beban tanpa mengganggu layanan.

Kesimpulannya adalah

Anda sekarang memiliki rencana lengkap untuk membangun DICOM anonymization microservice di ASP.NET Core. Layanan ini menerima file DIKOM melalui HTTP, menerapkan profil anonymisasi yang dapat dikonfigurasi menggunakan Aspose.Medical, dan mengembalikan file de-identifikasi siap untuk penelitian atau perkongsian.

Tugas-tugas utama termasuk menggunakan arsitektur lapisan untuk pemeliharaan, implementasi profil yang dapat dikonfigurasi untuk fleksibilitas, memastikan layanan dengan autentikasi dan enkripsi, dan mengoptimalkan kinerja dengan pemrosesan paralel.

Untuk kode sumber lengkap dan contoh tambahan, kunjungi Aspose.Dokumen PerubatanUntuk mencoba api, Dapatkan lisensi sementara gratis.

More in this category