Helseorganisasjoner trenger stadig mer automatiserte løsninger for å de-identifisere medisinske bildedata.I denne guiden vil du lære hvordan du bygger en DICOM anonymisering mikroservice i ASP.NET Core som mottar DIKOM-filer via HTTP, anonymiserer dem ved hjelp av konfigurerbare profiler, og returnerer de identifiserte resultatene.
Tabell av innhold
- arkitektonisk oversikt
- Sett opp prosjektet
- Implementering av Service Layer
- Bygge API-kontroller
- Konfigurerbare profiler
- Sikkerhetsoppfatninger
- Optimalisering av ytelse
- Conclusion
Oversikt over arkitektur
Mikroservice følger en lagret arkitektur med klar separasjon av bekymringer. API-laget håndterer HTTP-forespørsler og svar gjennom ASP.NET Core-kontroller. Tjenestelaget inneholder forretningslogikken ved hjelp av Aspose.Medical Anonymizer. Konfigurasjonslaget administrerer profilinnstillinger og applikasjonsalternativer. Valgkomponenter inkluderer lagring for logging og queuing for batchbehandling.
Denne arkitekturen tillater horisontal skalering, enkel testing og enkel integrering med sykehusinformasjonssystemer og PACS-servere.
Sett opp prosjektet
Start ved å lage et nytt ASP.NET Core Web API-prosjekt og installere det nødvendige pakken:
dotnet new webapi -n DicomAnonymizationService
cd DicomAnonymizationService
dotnet add package Aspose.Medical
Konfigurer prosjektet for store filopptak 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();
Implementering av Service Layer
Lag en grensesnitt 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);
}
}
Bygg API-kontrollen
Skap en kontroller som håndterer filopptak og returnerer anonymiserte 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"]
}
}
}
Lag en konfigurasjonsklasse og oppdater tjenesten for å lese fra innstillinger:
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 av sikkerhetsvurderinger
Ved implementering av denne tjenesten, implementere disse sikkerhetsforanstaltningene.
Aktiver HTTPS for å sikre at alle kommunikasjonene er kryptert i transitt. Konfigurer TLS 1.2 eller høyere og omdirigere hTTP til https.
Implementasjon autentisering ved hjelp av JWT tokener eller API-nøkler for å begrense tilgangen til autoriserte kunder:
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class AnonymizeController : ControllerBase
{
// Controller code...
}
Unngå å lagre opprinnelige filer ikke kryptert på disk. Behandle filene i hukommelsen når det er mulig, og hvis midlertidig lagring er nødvendig, bruk kryptet volum.
Hjelper revisjonslogging for å spore alle anonymiseringsoperasjoner, inkludert hvem som ba om dem og når:
_logger.LogInformation(
"Anonymization completed - User: {User}, Profile: {Profile}, FileSize: {Size}",
User.Identity?.Name, profile, file.Length);
Optimering av ytelse (performance optimization)
Flere teknikker kan forbedre ytelsen for high-throughput scenarier.
Anonymisering på plass når du ikke trenger å beholde de opprinnelige dataene i hukommelsen:
anonymizer.AnonymizeInPlace(dcm);
Hjelper parallell bearbeiding for batchoperasjoner:
[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...
}
Implementere forespørsel om queuing for veldig store partier ved hjelp av en melding queue som RabbitMQ eller Azure Service Bus for å håndtere lastspikes uten å overvelde tjenesten.
Konklusjon #konklusjonen
Du har nå en fullstendig planlegging for å bygge en DICOM anonymisering mikroservice i ASP.NET Core. Tjenesten aksepterer DIKOM-filer via HTTP, bruker konfigurerbare anonymiseringsprofiler ved hjelp av Aspose.Medical, og returnerer de-identifiserte filer klar for forskning eller deling.
Nøkkeloppgaver inkluderer bruk av lagret arkitektur for vedlikehold, implementering av konfigurable profiler for fleksibilitet, sikring av tjenesten med autentisering og kryptering, og optimalisering av ytelse med parallell behandling.
For full kildekode og ytterligere eksempler, besøk Aspose.Medisinsk dokumentasjonFor å prøve ild, Få gratis midlertidig lisens.
More in this category
- Forberedelse av DICOM-datasett for AI og maskinlæring med Aspose.Medical
- Hvorfor DICOM Anonymisering er viktig for HIPAA og GDPR i .NET Workflows
- Tilpassede konfidensialitetsprofiler som tilpasser DICOM-anonymisering til sykehuspolitikken din
- Lagre DICOM metadata i SQL og NoSQL-databaser med C#
- DICOM Anonymisering for Cloud PACS og Teleradiologi i C#