Terveydenhuollon organisaatiot tarvitsevat yhä enemmän automatisoituja ratkaisuja lääketieteellisten kuvatietojen tunnistamiselle. Tässä oppaassa opit rakentamaan DICOM-anonyymiä koskeva mikroservice ASP.NET Core, joka vastaanottaa HTTP-tiedostoja, anonymisoi ne konfiguroitavien profiilien avulla ja palauttaa tunnistetut tulokset.

Sisällön taulukko

Arkkitehtuurin yleiskuva

Microservice seuraa kerroksinen arkkitehtuuri selkeällä erottamisella huolenaiheista. API-laatikko käsittelee HTTP-pyyntöjä ja vastauksia ASP.NET Core -ohjainten kautta. Palvelulaati sisältää liiketoiminnan logiikan käyttämällä Aspose.Medical Anonymizer. Konfiguraatiolaaja hallitsee profiilin asetuksia ja sovellusvaihtoehtoja. Valinnaiset komponentit sisältävät tallennuksen kirjautumiseen ja kuvan käsittelyyn.

Tämä arkkitehtuuri mahdollistaa horisontaalisen mittakaavan, helppo testaus ja yksinkertainen integrointi sairaalan tietojärjestelmiin ja PACS-palvelimiin.

Ohjelman asettaminen

Aloita luomalla uusi ASP.NET Core Web API -hanke ja asentamalla tarvittava paketti:

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

Suorita projekti suurille tiedostojen latauksille 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();

Käytännön toteuttaminen Service Layer

Luo käyttöliittymä ja täytäntöönpano anonymisointipalvelulle:

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

Rakenna API-ohjain

Luo ohjain, joka hallinnoi tiedostojen latauksia ja palauttaa anonyymejä DICOM-tiedostoja:

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

Konfiguratiiviset profiilit

Suosittelemme, että profiilit voidaan konfiguroida appsettings.json:

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

Luo konfigurointiluokka ja päivitä palvelua lukemaan asetuksista:

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

Turvallisuuskysymykset

Käytettäessä tätä palvelua, toteutetaan nämä turvatoimenpiteet.

HTTPS-yhteys varmistaa, että kaikki viestinnät on salattu liikenteessä. määritä TLS 1.2 tai korkeampi ja ohjaa HTTP Https.

Sovelluksen todentaminen JWT-tokenien tai API-näppäimien avulla rajoittaa pääsyä valtuutettuihin asiakkaisiin:

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

Voit tallentaa alkuperäisiä tiedostoja, jotka eivät ole salattuja levylle. käsittele tiedostot muistiin, kun se on mahdollista, ja jos tilapäistä tallennusta tarvitaan, käytä salaettuja määriä.

Voita tarkastuksen kirjaaminen seuraamaan kaikkia nimettömyysoperaatioita, mukaan lukien kuka pyytää niitä ja kun:

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

suorituskyvyn optimointi (performance optimization)

Useat tekniikat voivat parantaa suorituskykyä korkean läpimurron skenaarioissa.

Käytä paikallinen anonymisointi, kun alkuperäisiä tietoja ei tarvitse säilyttää muistiin:

anonymizer.AnonymizeInPlace(dcm);

Sovelletaan rinnakkaista käsittelyä batch-toiminnalle:

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

*Sovellus pyytää kiusaamista hyvin suurille matkoille, jotka käyttävät viestikuvia, kuten RabbitMQ tai Azure Service Bus, käsittelemään kuorma-aukkoja ilman palvelun liioittelua.

Yhteenveto #päätös

Sinulla on nyt täydellinen suunnitelma rakentaa DICOM anonymization microservice ASP.NET Core. Palvelu hyväksyy DICom-tiedostoja HTTP:n kautta, soveltaa konfiguroituja anonymisointiprofiileja käyttämällä Aspose.Medical ja palauttaa tunnistetut tiedostot valmiiksi tutkimukseen tai jakamiseen.

Tärkeimpiä tehtäviä ovat laatuarkkitehtuurin käyttö ylläpitoon, konfiguroitujen profiilien toteuttaminen joustavuuden varmistamiseksi, palvelun turvaaminen todentamisen ja salauksen avulla sekä suorituskyvyn optimointi rinnakkaisen käsittelyn avulla.

Täyden lähdekoodin ja lisää esimerkkejä, katso ASPOSE. lääketieteellinen dokumenttiKokeilemaan tulipaloa, Saat ilmaisen väliaikaisen lisenssin.

More in this category