Gesundheitsorganisationen benötigen zunehmend automatisierte Lösungen für die De-identifizierung von medizinischen Bilddaten. In diesem Leitfaden erfahren Sie, wie Sie einen DICOM-Anonymisierung-Mikroservice in ASP.NET Core erstellen können, der DICO-Dateien über HTTP empfängt, sie mit konfigurierbaren Profilen anonymisiert und die de-identifizierten Ergebnisse zurückgibt.
Tabelle der Inhalte
- Architektur Überblick
- Planung des Projekts
- Implementieren der Service Layer
- Aufbau der API-Controller
- Konfigurierbare Profile
- Sicherheitsgründe
- Leistungsoptimierung
- Schlussfolgerungen
Architektur Überblick
Der Microservice folgt einer layered Architektur mit klarem Trennung von Sorgen. Die API-Schicht behandelt HTTP-Anfragen und Antworten über ASP.NET Core-Controller. Der Service-Schicht enthält die Geschäftslogik mit der Aspose.Medical Anonymizer. Das Konfigurationsschicht verwalt Profilinstellungen und Anwendungsoptionen. Optionale Komponenten umfassen Speicher für Logging und Queuing für Batch-Verarbeitung.
Diese Architektur ermöglicht horizontale Skalierung, einfache Testung und einfachen Integrationen mit Krankenhausinformationssystemen und PACS-Server.
Einrichten des Projekts
Beginnen Sie mit der Erstellung eines neuen ASP.NET Core Web API-Projekts und installieren Sie das erforderliche Paket:
dotnet new webapi -n DicomAnonymizationService
cd DicomAnonymizationService
dotnet add package Aspose.Medical
Konfigurieren Sie das Projekt für große Dateiübertragungen in 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();
Implementieren der Service Layer
Erstellen einer Schnittstelle und Implementierung für den Anonymisierungsdienst:
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);
}
}
Aufbau des API-Controller
Erstellen Sie einen Controller, der Dateien hochgeladen und anonymisierte DICOM-Dateien zurückgibt:
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);
}
}
Konfigurierbare Profile
Profile können konfiguriert werden durch appsettings.json:
{
"AnonymizationProfiles": {
"default": "basic",
"profiles": {
"basic": ["BasicProfile"],
"research": ["BasicProfile", "RetainPatientChars"],
"internal": ["RetainUIDs", "RetainDeviceIdent"],
"clean": ["CleanGraph", "CleanDesc"],
"maximum": ["BasicProfile", "CleanGraph", "CleanDesc"]
}
}
}
Erstellen Sie eine Konfigurationsklasse und aktualisieren Sie den Service, um aus den Einstellungen zu lesen:
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"));
Sicherheitsgründe
Wenn Sie diesen Service implementieren, setzen Sie diese Sicherheitsmaßnahmen ein.
HTTPS ermöglicht, um sicherzustellen, dass alle Kommunikationen im Transit verschlüsselt sind. Konfigurieren Sie TLS 1.2 oder höher und HTTP nach https umleiten.
Implementierungs-Authentifizierung mit JWT-Token oder API-Schlüssen, um den Zugang zu autorisierten Kunden zu beschränken:
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class AnonymizeController : ControllerBase
{
// Controller code...
}
Vermeiden Sie die Speicherung der ursprünglichen Dateien**, die nicht auf dem Festplatten verschlüsselt sind.Verarbeiten Sie Dateien im Speicher, wenn möglich, und wenn vorübergehendes Speichern erforderlich ist, verwenden Sie Verschlüsselte Volumen.
Ein Auditlogging ermöglicht, um alle Anonymisierungsoperationen zu verfolgen, einschließlich derjenigen, die sie angefordert haben und wenn:
_logger.LogInformation(
"Anonymization completed - User: {User}, Profile: {Profile}, FileSize: {Size}",
User.Identity?.Name, profile, file.Length);
Leistungsoptimierung = Performance Optimization
Mehrere Techniken können die Leistung für High-through-Put-Szenarien verbessern.
Anonymisierung im Standort verwenden, wenn Sie die ursprünglichen Daten nicht im Speicher speichern müssen:
anonymizer.AnonymizeInPlace(dcm);
Parallelverarbeitung ermöglicht für Batch-Betrieb:
[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...
}
Implementieren Sie die Anforderung von Quoiing für sehr große Batches mit einer Nachrichtquoi wie RabbitMQ oder Azure Service Bus, um Ladespikes ohne den Service zu überwältigen.
Schlussfolgerung
Sie haben jetzt ein vollständiges Plugin für die Erstellung eines DICOM-Anonymisierung-Mikroservices in ASP.NET Core. Der Service akzeptiert DICO-Dateien über HTTP, angewendet konfigurierbare anonymisierungsprofile mit Aspose.Medical und returns de-identified files ready for research or sharing.
Zu den wichtigsten Maßnahmen gehören die Verwendung von Layered Architecture für Wartungsfähigkeit, die Implementierung konfigurierbarer Profile für Flexibilität, Sicherung des Dienstes mit Authentifizierung und Verschlüsselung und die Optimierung der Leistung mit paralleller Verarbeitung.
Für den vollständigen Quellcode und weitere Beispiele, besuchen Sie die Aspose.Medizinische DokumentationUm das Feuer zu versuchen, Erhalten Sie eine kostenlose vorübergehende Lizenz.
More in this category
- Personalisierte Privatsphäre-Profile, die die Anonymisierung von DICOM an Ihre Krankenhausrichtlinien anpassen
- Vorbereitung von DICOM-Datasets für AI und Machine Learning mit Aspose.Medical
- Warum DICOM Anonymisierung für HIPAA und GDPR in .NET Workflows wichtig ist
- Speichern Sie DICOM Metadata in SQL und NoSQL-Datenbanken mit C#
- DICOM Anonymisierung für Cloud PACS und Teleradiologie in C#