ארגוני הבריאות זקוקים יותר ויותר לפתרונות אוטומטיים לזיהוי נתוני התמונה הרפואית.במדריך זה תוכלו ללמוד כיצד לבנות מיקרו-שירות אננימיזציה של DICOM ב- ASP.NET Core** אשר מקבל קבצי DIKOM באמצעות HTTP, אנונימיים אותם באמצעות פרופילים אפשריים, ומחזירים את התוצאות האותיות.בסופו של דבר, תהיה לכם ארכיטקטורה שירות מוכנה לייצור עם קוד מקור דגימה.
שולחן התוכן
- ארכיטקטורה סקירה
- הגדרת הפרויקט
- יישום שכבת השירות
- בניית מנהל ה- API
- פרופילים אפשריים
- שיקולים ביטחוניים
- אופטימיזציה ביצועים
- מסקנה
ארכיטקטורה סקירה כללית
מיקרו-שירות עוקב אחר ארכיטקטורה שכבה עם הפרדה ברורה של דאגות. שכבת ה- API מתמודדת עם בקשות HTTP ותשובות באמצעות ASP.NET Core Controller. השכבת השירות מכילה את ההיגיון העסקי באמצעות Aspose.Medical Anonymizer. כיסוי ההגדרה מנהל הגדרות פרופיל ואפשרויות יישום.
ארכיטקטורה זו מאפשרת סיווג אופקי, בדיקות קלות ואינטגרציה פשוטה עם מערכות מידע בתי חולים ושירותי PACS.
הגדרת הפרויקט
התחל עם יצירת פרויקט חדש של ASP.NET Core Web API ולהתקין את החבילה הנדרשת:
dotnet new webapi -n DicomAnonymizationService
cd DicomAnonymizationService
dotnet add package Aspose.Medical
הגדרת הפרויקט להעלאת קבצים גדולים 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();
יישום שכבת השירות
יצירת ממשק ויישום עבור שירות האנימציה:
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
יצירת מנהל שמנהל את העלאות הקבצים ומחזיר קבצי DICOM אנונימיים:
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);
}
}
פרופילים אפשריים
אפשרות להגדיר פרופילים באמצעות appsettings.json:
{
"AnonymizationProfiles": {
"default": "basic",
"profiles": {
"basic": ["BasicProfile"],
"research": ["BasicProfile", "RetainPatientChars"],
"internal": ["RetainUIDs", "RetainDeviceIdent"],
"clean": ["CleanGraph", "CleanDesc"],
"maximum": ["BasicProfile", "CleanGraph", "CleanDesc"]
}
}
}
יצירת שיעור הגדרה ולעדכן את השירות כדי לקרוא מההגדרות:
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"));
שיקול דעת בטיחות[עריכת קוד מקור עריכה]
בעת הפעלת שירות זה, יישום אמצעי אבטחה אלה.
אפשר HTTPS כדי להבטיח כי כל התקשורת מוצפנת במהלך המעבר.הגדיר TLS 1.2 או גבוה יותר ולהעביר את http ל http.
אמת יישום באמצעות טוקנים JWT או מפתחות API כדי להגביל את הגישה ללקוחות מורשים:
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class AnonymizeController : ControllerBase
{
// Controller code...
}
ימנעו מאחסנים של קבצים מקוריים שאינם מוצפנים על הדיסק.עבדו את הקבצי בזיכרון ככל האפשר, ואם אחסון זמני נדרש, השתמשו בגודל מוצפן.
אפשר גישה לביקורת כדי לעקוב אחר כל פעולות האנונימיות, כולל מי ביקש אותן וכאשר:
_logger.LogInformation(
"Anonymization completed - User: {User}, Profile: {Profile}, FileSize: {Size}",
User.Identity?.Name, profile, file.Length);
אופטימיזציה ביצועים – Performance Optimization
מספר טכניקות יכולות לשפר את הביצועים עבור סרטי פריצת דרך גבוהה.
אנונימיזציה מקומית כאשר אינך צריך לשמור את הנתונים המקוריים בזיכרון:
anonymizer.AnonymizeInPlace(dcm);
אפשר עיבוד מקביל עבור פעולות חבילה:
[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...
}
יישום בקשה לקווינג עבור חבילות גדולות מאוד באמצעות קווי הודעות כגון RabbitMQ או Azure Service Bus כדי להתמודד עם ספיקים של משאבים בלי להתעלם מהשירות.
מסקנה #הסכם
עכשיו יש לך תוכנית מלאה לבניית DICOM אנונימיזציה מיקרו-שירות ב- ASP.NET Core. השירות מקבל קבצי DICO באמצעות HTTP, יישום פרופילים אננימיים מותאמים אישית באמצעות Aspose.Medical, ומחזיר את הקבצים הלא מזהים מוכנים למחקר או לשיתוף.
נושאים עיקריים כוללים שימוש בארכיטקטורה שכבה לתחזוקה, יישום פרופילים מותאמים לגמישות, אבטחת השירות עם זיהוי והצפנה, אופטימיזציה ביצועים עם עיבוד מקביל.
לקבלת קוד מקור מלא ודוגמאות נוספות, ראה תגית: מסמכים רפואייםכדי לנסות את האש, קבל רישיון זמני חינם.
More in this category
- הכנת נתונים של DICOM ל- AI ולמידה מכונה עם Aspose.Medical
- מדוע DICOM Anonymization חשוב עבור HIPAA ו GDPR ב .NET Workflows
- פרופילים פרטיות מותאמים אישית המתאימים ל-DICOM Anonymization למדיניות בית החולים שלך
- אחסון נתונים DICOM ב- SQL ו- NoSQL עם C#
- DICOM Anonymization for Cloud PACS and Teleradiology ב- C#