Organizațiile de asistență medicală au nevoie din ce în ce mai mult de soluții automatizate pentru dezidentificarea datelor cu imagini medicale.În acest ghid, veți învăța cum să construiți un microservice de anonimizare DICOM în ASP.NET Core** care primește fișierele DIKOM prin HTTP, le anonimizează folosind profiluri configurabile și returnează rezultatele de-identifice.

Tabelul conținutului

Arhitectură de ansamblu

Microservice urmează o arhitectură stratată cu o separare clară a preocupărilor. stratul API gestionează solicitările și răspunsurile HTTP prin intermediul controlorilor de bază ASP.NET. Layerul de serviciu conține logica afacerii folosind Aspose.Medical Anonymizer. layer de configurare administrează setările de profil și opțiunile de aplicare. componentele opționale includ stocarea pentru înregistrare și chewing pentru prelucrarea batch-ului.

Această arhitectură permite scalarea orizontală, testarea ușoară și integrarea simplă cu sistemele de informare a spitalelor și cu serverele PACS.

Afișarea proiectului

Începeți prin crearea unui nou proiect ASP.NET Core Web API și instalarea pachetului necesar:

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

Configurați proiectul pentru fișierele mari încărcate în 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();

Implementarea Layerului Serviciului

Creați o interfață și o implementare pentru serviciul de anonimizare:

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

Construirea controlorului API

Creați un controlor care gestionează upload-urile de fișiere și returnează fișierele DICOM anonime:

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

Profile configurabile

Permite ca profilurile să fie configurate prin appsettings.json:

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

Creați o clasă de configurare și actualizați serviciul pentru a citi din setări:

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

Considerații de securitate

Atunci când implementați acest serviciu, puneți în aplicare aceste măsuri de securitate.

Activați HTTPS pentru a se asigura că toate comunicațiile sunt criptate în tranzit. Configurează TLS 1.2 sau mai mare și redirecționează http la http.

Autentificarea implementării folosind tokenele JWT sau cheile API pentru a restricționa accesul la clienții autorizați:

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

Să evitați stocarea fișierelor originale necryptate pe disc.File de procesare sunt în memorie atunci când este posibil și, dacă este necesar depozitarea temporară, utilizați volumele cifrate.

Să permită înregistrarea auditului pentru a urmări toate operațiunile de anonimizare, inclusiv cine le-a solicitat și când:

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

Optimizarea performanţelor

Mai multe tehnici pot îmbunătăți performanța pentru scenarii de înaltă performanță.

Utilizarea anonimizării în loc atunci când nu aveți nevoie să păstrați datele originale în memorie:

anonymizer.AnonymizeInPlace(dcm);

Activă prelucrarea paralelă pentru operațiunile de 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...
}

Implementarea cererii de chewing pentru batch-uri foarte mari folosind o cheie de mesaje cum ar fi RabbitMQ sau Azure Service Bus pentru a gestiona picăturile de încărcare fără a supraîncărca serviciul.

Concluziune #conclusie

Acum aveți un plan complet pentru a construi un microservice de anonimizare DICOM în ASP.NET Core**. Serviciul acceptă fișierele DIKOM prin intermediul HTTP, aplică profiluri de anonimizare configurabile folosind Aspose.Medical și returnează fișiere de-identificate pregătite pentru cercetare sau partajare.

Principiile cheie includ utilizarea arhitecturii stratate pentru întreținere, implementarea profilurilor configurabile pentru flexibilitate, asigurarea serviciului prin autentificare și criptare, precum și optimizarea performanței prin prelucrare paralelă.

Pentru codul sursă complet și exemple suplimentare, vizitați Aspose.Documentație medicalăPentru a încerca focul, Obțineți o licență temporară gratuită.

More in this category