Veselības aprūpes organizācijām arvien vairāk vajadzīgi automatizēti risinājumi, lai de-identificētu medicīnisko attēlu datus. Šajā vadlīnijā jūs uzzināsiet, kā izveidot DICOM anonimizācijas mikroservisu ASP.NET Core, kas saņem DIKOM failus caur HTTP, anonimitē tos, izmantojot konfigurējamus profilus, un atgriežas deidentificētos rezultātos.
satura tabula
- Arhitektūras pārskats
- Projekta izveidošana
- Pakalpojumu slāņa īstenošana
- Izveidojiet API kontrolieri
- Konfigurētie profili
- Drošības apsvērumi
- Darbības optimizācija
- Conclusion
Arhitektūras pārskats
Microservice seko slāņa arhitektūra ar skaidru atdalīšanos no bažām. API slāni apstrādā HTTP pieprasījumus un atbildes caur ASP.NET Core kontroleriem. Pakalpojumu līmenis satur biznesa loģiku, izmantojot Aspose.Medical Anonymizer. Konfigurācijas līmeņi pārvalda profila iestatījumiem un lietojumprogrammas iespējas. Opcionālie komponenti ietver uzglabāšanu logging un quuing batch apstrādei.
Šī arhitektūra ļauj horizontālu skalēšanu, viegli pārbaudīt un vienkāršu integrāciju ar slimnīcas informācijas sistēmām un PACS serveriem.
Projekta izveidošana
Sāciet, izveidojot jaunu ASP.NET Core Web API projektu un instalējot nepieciešamo paketi:
dotnet new webapi -n DicomAnonymizationService
cd DicomAnonymizationService
dotnet add package Aspose.Medical
Iestatīt projektu lieliem failu lejupielādējumiem 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();
Pakalpojuma slāņa īstenošana
Izveidojiet saskarni un ieviešanu anonimizācijas pakalpojumam:
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);
}
}
Izveidojiet API kontrolieri
Izveidojiet kontrolieri, kas apstrādā failu lejupielādes un atgriežas anonīmi DICOM faili:
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);
}
}
Konfigurējami profili
Atļauj profilus konfigurēt, izmantojot appsettings.json:
{
"AnonymizationProfiles": {
"default": "basic",
"profiles": {
"basic": ["BasicProfile"],
"research": ["BasicProfile", "RetainPatientChars"],
"internal": ["RetainUIDs", "RetainDeviceIdent"],
"clean": ["CleanGraph", "CleanDesc"],
"maximum": ["BasicProfile", "CleanGraph", "CleanDesc"]
}
}
}
Izveidojiet konfigurācijas klases un atjauniniet pakalpojumu, lai izlasītu no iestatījumiem:
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"));
Drošības apsvērumi
Izmantojot šo pakalpojumu, īstenojiet šos drošības pasākumus.
Iegūstiet HTTPS, lai nodrošinātu, ka visas saziņas ir šifrētas tranzīta laikā.
Implementa autentifikācija, izmantojot JWT tokenus vai API atslēgas, lai ierobežotu piekļuvi pilnvarotajiem klientiem:
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class AnonymizeController : ControllerBase
{
// Controller code...
}
Izvairieties no oriģinālo failu uzglabāšanas, kas nav šifrēti uz diska.
Iegūstiet revīzijas ierakstu, lai uzraudzītu visas anonimizācijas operācijas, tostarp, kas to pieprasīja un kad:
_logger.LogInformation(
"Anonymization completed - User: {User}, Profile: {Profile}, FileSize: {Size}",
User.Identity?.Name, profile, file.Length);
Darbības optimizācija
Vairākas tehnikas var uzlabot veiktspēju augstas efektivitātes scenārijos.
Izmantojiet anonimizāciju, ja jums nav nepieciešams saglabāt sākotnējos datus atmiņā:
anonymizer.AnonymizeInPlace(dcm);
Iegūstiet paralēli apstrādi batch operācijām:
[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...
}
Implementa pieprasījums kavēt ļoti lieliem gabaliem, izmantojot ziņojumu kavējumu, piemēram, RabbitMQ vai Azure Service Bus, lai apstrādātu slodzes spikes bez pārspīlēšanas pakalpojumu.
Noslēgums #Konklusija
Tagad jums ir pilns plānojums, lai izveidotu DICOM anonimizācijas mikroservisu ASP.NET Core. Pakalpojums pieņem DIKOM failus caur HTTP, piemēro konfigurējamus anonimitācijas profilus, izmantojot Aspose.Medical, un atgriež de-identificētus failu, kas ir gatavi pētniecībai vai dalībai.
Galvenie uzdevumi ietver laistīto arhitektūru izmantošanu uzturam, konfigurējamu profilu ieviešanu elastīgumam, pakalpojumu nodrošināšanu ar autentifikāciju un šifrēšanu un veiktspējas optimizāciju ar paralēlu apstrādi.
Lai iegūtu pilnīgu avota kodu un papildu piemērus, apmeklējiet Aspose.Medicīnas dokumentācijaLai izmēģinātu uguni, Iegūstiet brīvu pagaidu licenci.
More in this category
- Kāpēc DICOM anonimizācija nozīmē HIPAA un GDPR .NET darba plūsmās
- Personalizēti konfidencialitātes profili, kas pielāgo DICOM anonimizāciju Jūsu slimnīcas politikai
- Sagatavo DICOM datasetus AI un mašīnas mācīšanai ar Aspose.Medical
- DICOM metadatu uzglabāšana SQL un NoSQL datu bāzēs ar C#
- DICOM Anonimizācija par mākoņu PACS un Teleradioloģiju C#