Sveikatos priežiūros organizacijoms vis dažniau reikia automatizuotų sprendimų de-identifikuoti medicinos vaizdo duomenis. Šiame vadove sužinosite, kaip sukurti DICOM anonimiškumo mikroserviziją ASP.NET Core, kuri gauna DIKOM failus per HTTP, anonimizuoja juos naudojant konfigūruojamus profilius ir grąžina deidentuotus rezultatus.
Turinio lentelė
- Architektūros apžvalga
- Įdiegti projektą
- Paslaugų sluoksnio įgyvendinimas
- Įdiegti API kontrolierių
- Konfiguruoti profilius
- Saugumo apžvalgos
- Veiksmingumo optimizavimas
- Conclusion
Architektūros apžvalga
Microservice sekia sluoksnį architektūrą su aiškiu susirūpinimo atskyrimu. API lapas tvarko HTTP užklausas ir atsakymus per ASP.NET Core valdytojus. Paslaugos laipsnis apima verslo logiką naudojant Aspose.Medical Anonymizer. Konfiguravimo lašas valdo profilio nustatymus ir taikymo parinktis.
Ši architektūra leidžia horizontalią skalavimą, lengvą bandymą ir paprastą integraciją su ligoninės informacinėmis sistemomis ir PACS serveriais.
Įdiegti projektą
Pradėkite kurti naują ASP.NET Core Web API projektą ir įdiegti reikalingą paketą:
dotnet new webapi -n DicomAnonymizationService
cd DicomAnonymizationService
dotnet add package Aspose.Medical
Konfigūruokite projektą dideliems failų įkrovimams 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();
Paslaugų sluoksnio įgyvendinimas
Sukurkite sąsają ir įgyvendinimą anonimiškumo paslaugai:
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);
}
}
API valdytojo kūrimas
Sukurkite valdytoją, kuris tvarko failų atsisiuntimus ir grąžina anonimiškus DICOM failus:
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);
}
}
Konfiguruoti profilius
Leiskite profiliams konfigūruoti per appsettings.json:
{
"AnonymizationProfiles": {
"default": "basic",
"profiles": {
"basic": ["BasicProfile"],
"research": ["BasicProfile", "RetainPatientChars"],
"internal": ["RetainUIDs", "RetainDeviceIdent"],
"clean": ["CleanGraph", "CleanDesc"],
"maximum": ["BasicProfile", "CleanGraph", "CleanDesc"]
}
}
}
Sukurkite konfigūracijos klasę ir atnaujinkite paslaugą skaityti iš nustatymų:
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"));
Saugumo apžvalgos {# saugos apžiūros}
Taikydami šią paslaugą, įgyvendinkite šias saugos priemones.
Įveskite HTTPS užtikrinti, kad visos komunikacijos būtų užšifruotos tranzito metu. konfigūruokite TLS 1.2 ar aukštesnį ir persiųskite „HTTP“ į „HTPS“.
Įgyvendinimo autentifikavimas naudojant JWT tokenus arba API raktus, kad būtų ribojamas prieiga į autorizuotus klientus:
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class AnonymizeController : ControllerBase
{
// Controller code...
}
Nereikia saugoti originalių failų*, kurie nėra šifruoti diske.Kai įmanoma, tvarkykite failus atmintyje ir, jei reikia laikinos saugojimo, naudokite šifrintų tūrių.
Sugebėjimas registruoti auditą, kad būtų galima stebėti visas anonimiškumo operacijas, įskaitant tai, kas juos paprašė, ir kai:
_logger.LogInformation(
"Anonymization completed - User: {User}, Profile: {Profile}, FileSize: {Size}",
User.Identity?.Name, profile, file.Length);
Veiksmų optimizavimas
Įvairūs metodai gali pagerinti aukštos kokybės scenarijus.
Naudokite anonimiškumą vietoje, kai nereikia išsaugoti originalių duomenų atmintyje:
anonymizer.AnonymizeInPlace(dcm);
Paralelinė apdorojimo galimybė batch operacijoms:
[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...
}
Implementavimo prašymas kreiptis labai dideliems batams naudojant pranešimų kreivę, pvz., RabbitMQ arba Azure Service Bus, kad būtų galima tvarkyti apkrovos spikes be pernelyg didelio aptarnavimo.
Išvada – išvadas
Dabar turite išsamią plokštelę, kad sukurtumėte „DICOM“ anonimiškumo mikroserviziją „ASP.NET Core“**. Paslauga priima „HTTP“ duomenis, taiko konfigūruojamus anoniminio pobūdžio profilius naudojant „Aspose.Medical“ ir grąžina de-identifikuotus failus, kurie yra paruošti tyrimui ar dalijimui.
Pagrindiniai veiksmai apima sluoksnio architektūros naudojimą tvarumui, konfigūruojamų profilių įgyvendinimą lanksčiai, paslaugų užtikrinimą autentiškumu ir šifravimu ir veiklos optimizavimą lygiagrečiu apdorojimu.
Norėdami gauti išsamią šaltinio kodą ir papildomus pavyzdžius, apsilankykite Aspose.Medicininė dokumentacijaIšbandyti ugnį, Gaukite nemokamą laikiną licenciją.
More in this category
- DICOM duomenų rinkinys AI ir mašinų mokymui su Aspose.Medical
- Kodėl DICOM anonimiškumas svarbus HIPAA ir GDPR .NET darbo srautams
- Pritaikyti konfidencialumo profiliai, pritaikantys DICOM anonimiškumą jūsų ligoninės politikai
- DICOM metaduomenų saugojimas SQL ir NoSQL duomenų bazėse C#
- DICOM anonimizavimas debesų PACS ir Teleradiologijos C#