Các tổ chức chăm sóc sức khỏe ngày càng cần các giải pháp tự động để mất nhận dạng dữ liệu hình ảnh y tế. Trong hướng dẫn này, bạn sẽ tìm hiểu làm thế nào để xây dựng một DICOM anonimization microservice trong ASP.NET Core mà nhận được các tập tin DICO thông qua HTTP, anonymizes chúng bằng cách sử dụng các hồ sơ có thể cấu hình, và trả về kết quả không xác định.
Bảng nội dung
- kiến trúc tổng quan
- Thiết lập dự án
- Thực hiện Layer Service
- Xây dựng API Controller
- cấu hình profile
- Quan điểm an ninh
- Tối ưu hóa hiệu suất
- Kết luận
Tổng quan kiến trúc
Microservice theo một kiến trúc lớp với sự phân biệt rõ ràng của mối quan tâm. lớp API xử lý các yêu cầu HTTP và câu trả lời thông qua các bộ điều khiển ASP.NET Core. Layer dịch vụ chứa logic kinh doanh sử dụng Aspose.Medical Anonymizer. The configuration layer manages profile settings and application options. Optional components include storage for logging and queuing for batch processing.
Kiến trúc này cho phép quy mô ngang, kiểm tra dễ dàng và tích hợp đơn giản với các hệ thống thông tin bệnh viện và máy chủ PACS.
Thiết lập dự án
Bắt đầu bằng cách tạo một dự án mới ASP.NET Core Web API và cài đặt gói yêu cầu:
dotnet new webapi -n DicomAnonymizationService
cd DicomAnonymizationService
dotnet add package Aspose.Medical
Thiết lập dự án cho file upload lớn trong 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();
Thực hiện Layer Service
Tạo một giao diện và thực hiện cho dịch vụ anonymization:
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);
}
}
Xây dựng bộ điều khiển API
Tạo một bộ điều khiển quản lý các bản tải file và trả về các tập tin DICOM vô danh:
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);
}
}
Các hồ sơ có thể cấu hình
Cho phép các hồ sơ được cấu hình qua appsettings.json:
{
"AnonymizationProfiles": {
"default": "basic",
"profiles": {
"basic": ["BasicProfile"],
"research": ["BasicProfile", "RetainPatientChars"],
"internal": ["RetainUIDs", "RetainDeviceIdent"],
"clean": ["CleanGraph", "CleanDesc"],
"maximum": ["BasicProfile", "CleanGraph", "CleanDesc"]
}
}
}
Tạo một lớp cấu hình và cập nhật dịch vụ để đọc từ cài đặt:
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"));
Các vấn đề an ninh {#cách bảo mật}
Khi triển khai dịch vụ này, thực hiện các biện pháp bảo mật này.
Cung cấp HTTPS để đảm bảo tất cả các thông tin được mã hóa trong quá trình giao thông.Cài đặt TLS 1.2 hoặc cao hơn và chuyển hướng Http sang https.
Tự xác thực thực hiện bằng cách sử dụng mã JWT hoặc khóa API để hạn chế quyền truy cập cho khách hàng được ủy quyền:
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class AnonymizeController : ControllerBase
{
// Controller code...
}
Tránh lưu trữ các tệp gốc** không được mã hóa trên ổ đĩa. xử lý các tập tin trong bộ nhớ khi có thể, và nếu bảo quản tạm thời là cần thiết, sử dụng khối lượng mã hoá.
Khả năng đăng ký kiểm toán** để theo dõi tất cả các hoạt động nhận dạng, bao gồm những người đã yêu cầu và khi:
_logger.LogInformation(
"Anonymization completed - User: {User}, Profile: {Profile}, FileSize: {Size}",
User.Identity?.Name, profile, file.Length);
Tối ưu hóa hiệu suất - Performance Optimization
Một số kỹ thuật có thể cải thiện hiệu suất cho các kịch bản tốc độ cao.
** Sử dụng danh tính tại chỗ** khi bạn không cần lưu trữ dữ liệu ban đầu trong bộ nhớ:
anonymizer.AnonymizeInPlace(dcm);
- Khả năng xử lý song song** cho các hoạt động nhó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...
}
Hành động yêu cầu quwing cho các gói rất lớn bằng cách sử dụng một quing thông điệp như RabbitMQ hoặc Azure Service Bus để xử lý các đỉnh tải mà không gây phiền nhiễu dịch vụ.
Kết luận = kết luận
Bây giờ bạn có một kế hoạch đầy đủ để xây dựng một DICOM anonimization microservice trong ASP.NET Core. Dịch vụ chấp nhận các tập tin DICO thông qua HTTP, áp dụng cấu hình hồ sơ anonymization bằng cách sử dụng Aspose.Medical, và trả về các tệp không được xác định sẵn sàng cho nghiên cứu hoặc chia sẻ.
Các vấn đề quan trọng bao gồm việc sử dụng kiến trúc lớp để duy trì, thực hiện các hồ sơ có thể cấu hình để linh hoạt, đảm bảo dịch vụ với xác thực và mã hóa, và tối ưu hóa hiệu suất với xử lý song song.
Đối với mã nguồn đầy đủ và các ví dụ bổ sung, hãy truy cập ASPOSE - Tài liệu y tếĐể thử lửa, Nhận giấy phép tạm thời miễn phí.
More in this category
- Chuẩn bị DICOM Datasets cho AI và Machine Learning với Aspose.Medical
- Hồ sơ riêng tư tùy chỉnh phù hợp với DICOM Anonymization cho Chính sách Bệnh viện của bạn
- Tại sao DICOM Anonymization quan trọng đối với HIPAA và GDPR trong dòng công việc .NET
- Lưu DICOM Metadata trong SQL và NoSQL Databases với C#
- DICOM Anonymization cho Cloud PACS và Teleradiology trong C#