I denne guide vil du lære, hvordan man opbygger en DICOM anonymisering mikroservice i ASP.NET Core, der modtager DICUM filer via HTTP, anonymiserer dem ved hjælp af konfigurable profiler, og returnerer de de-identificerede resultater.

Tabellen af indhold

Oversigt over arkitektur

Mikroservice følger en lageret arkitektur med klar adskillelse af bekymringer. API-laget håndterer HTTP anmodninger og svar gennem ASP.NET Core kontroller. Tjenestelaget indeholder forretningslogik ved hjælp af Aspose.Medical Anonymizer. Konfigurationslagen administrerer profilindstillinger og applikationsmuligheder. Optionelle komponenter omfatter lagring til logging og quuing til batch behandling.

Denne arkitektur giver mulighed for horisontalt skalering, nem testing og enkel integration med hospitaloplysningssystemer og PACS-servere.

Sæt projektet op

Start ved at oprette et nyt ASP.NET Core Web API-projekt og installere det nødvendige pakke:

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

Konfigurer projektet til store filopladninger i 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();

Udførelse af Service Layer

Oprett en grænseflade og implementering for anonymiseringstjenesten:

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

Opbygning af API-kontroller

Skab en kontroller, der håndterer filopladninger og returnerer anonyme DICOM-filer:

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

Konfigurerbare profiler

Profiler kan konfigureres via appsettings.json:

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

Skab en konfigurationsklasse og opdater tjenesten til at læse fra indstillingerne:

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

Beskyttelse af sikkerhedssikkerhed

Når du implementerer denne tjeneste, gennemfører du disse sikkerhedsforanstaltninger.

Anvend HTTPS for at sikre, at alle kommunikationer er krypteret i transit. Konfigurer TLS 1.2 eller højere og omdirigere hTTP til https.

Implementation autentisering ved hjælp af JWT tokens eller API-nøgler for at begrænse adgangen til autoriserede kunder:

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

** Undgå at opbevare originale filer** ikke krypteret på disken. behandle filerne i hukommelsen, når det er muligt, og hvis midlertidig lagring er nødvendigt, brug kryptede volumer.

Autoriserer revisionslogging til at spore alle anonymiseringsoperationer, herunder hvem der har anmodet om dem og når:

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

Optimering af ydeevne

Flere teknikker kan forbedre ydeevnen for high-throughput scenarier.

Anonymisering på stedet, når du ikke behøver at gemme de oprindelige data i hukommelsen:

anonymizer.AnonymizeInPlace(dcm);

Lad parallel behandling til batchoperationer:

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

Implementation forespørgsel om quuing for meget store partier ved hjælp af en besked quue som RabbitMQ eller Azure Service Bus til at håndtere lastspikes uden at overvælge tjenesten.

Konklusionen er

Du har nu en komplet planlægning for at opbygge en DICOM anonymisering mikroservice i ASP.NET Core. Tjenesten accepterer DIKOM-filer via HTTP, anvender konfigurable anonymiseringsprofiler ved hjælp af Aspose.Medical, og returnerer de-identificerede filer klar til forskning eller deling.

Nøgleforanstaltninger omfatter brug af lageret arkitektur for vedligeholdelse, implementering af konfigurable profiler for fleksibilitet, sikring af tjenesten med autentisering og kryptering og optimering af ydeevne med parallel behandling.

For den komplette kildekode og yderligere eksempler, besøg Medikamenter.Medicinsk dokumentationFor at prøve ilden, Få en gratis midlertidig licens.

More in this category