Organisasi penjagaan kesihatan semakin memerlukan penyelesaian automatik untuk de-identifikasi data imej perubatan.Dalam panduan ini, anda akan belajar bagaimana untuk membina DICOM anonimiti microservice dalam ASP.NET Core yang menerima fail DIKOM melalui HTTP, menganonimkan mereka menggunakan profil yang boleh dikonfigurasi, dan mengembalikan hasil yang tidak dikenal pasti.

Jadual Kandungan

Gambaran keseluruhan

Layer API mengendalikan permintaan HTTP dan jawapan melalui pengawal ASP.NET Core. layer perkhidmatan mengandungi logik perniagaan menggunakan Aspose.Medical Anonymizer. lapisan konfigurasi menguruskan tetapan profil dan pilihan aplikasi. komponen opsional termasuk penyimpanan untuk log dan kuing untuk pemprosesan batch.

Arsitektur ini membolehkan skalan horizontal, pemeriksaan mudah, dan integrasi yang mudah dengan sistem maklumat hospital dan pelayan PACS.

Menetapkan projek

Mulakan dengan mencipta projek baru ASP.NET Core Web API dan memasang pakej yang diperlukan:

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

Mengesetkan projek untuk fail besar muat naik dalam 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();

Pelaksanaan Layer Perkhidmatan

Mencipta antara muka dan pelaksanaan untuk perkhidmatan 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);
    }
}

Membina kawalan API

Mencipta pengawal yang mengendalikan muat naik fail dan mengembalikan fail DICOM yang dianonimkan:

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 boleh dikonfigurasi

Membolehkan 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"]
    }
  }
}

Mencipta kelas konfigurasi dan mengemas kini perkhidmatan untuk dibaca daripada tetapan:

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

Apabila melaksanakan perkhidmatan ini, melaksanakan langkah-langkah keselamatan ini.

Mengaktifkan HTTPS untuk memastikan semua komunikasi disulitkan dalam transit.Pengaturan TLS 1.2 atau lebih tinggi dan mengarahkan hTTP ke Https.

Pengesahan pelaksanaan menggunakan token JWT atau kunci API untuk mengehadkan akses kepada pelanggan yang diberi kuasa:

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

Jangan menyimpan fail asal yang tidak disulitkan pada cakera.Proses fail dalam memori apabila mungkin, dan jika penyimpanan sementara diperlukan, gunakan jumlah yang tersulit.

Membolehkan log audit untuk memantau semua operasi anonim termasuk siapa yang meminta mereka dan apabila:

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

Pengoptimuman prestasi (Performance optimization)

Pelbagai teknik boleh meningkatkan prestasi untuk senario kecepatan tinggi.

Menggunakan anonimiti di tempat apabila anda tidak perlu menyimpan data asal dalam memori:

anonymizer.AnonymizeInPlace(dcm);

Mengaktifkan pemprosesan 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...
}

Mengimplementasikan permintaan kuing untuk batch yang sangat besar menggunakan kuin mesej seperti RabbitMQ atau Azure Service Bus untuk mengendalikan puncak beban tanpa mengganggu perkhidmatan.

Kesimpulannya ialah

Anda kini mempunyai rancangan lengkap untuk membina DICOM anonimization microservice dalam ASP.NET Core. Perkhidmatan ini menerima fail DIKOM melalui HTTP, memohon profil anonymization yang boleh dikonfigurasi menggunakan Aspose.Medical, dan mengembalikan fail de-identifikasi bersedia untuk penyelidikan atau perkongsian.

Tindakan utama termasuk menggunakan seni bina lapisan untuk penyelenggaraan, melaksanakan profil yang boleh dikonfigurasi untuk fleksibiliti, memastikan perkhidmatan dengan pengesahan dan penyulitan, dan mengoptimumkan prestasi dengan pemprosesan serentak.

Untuk kod sumber lengkap dan contoh tambahan, lihat Aspose.Dokumen Perubatanuntuk mencuba api, Dapatkan lesen sementara percuma.

More in this category