Wie man Async DICOM JSON Serialisierung in ASP.NET Core Web APIs verwendet

Wie man Async DICOM JSON Serialisierung in ASP.NET Core Web APIs verwendet

Dieses Tutorial zeigt, wie man die Async DICOM JSON-Serialisierung in ASP.NET Core Web APIs verwenden kann. Asynec-Dienstleistungen sind für Hochleistungswebanwendungen unerlässlich, um thread-blocking zu verhindern und die Reaktionsfähigkeit unter Ladung zu erhalten.

Warum Async Serialisierung?

  • Skalierbarkeit:- Nicht-Blocking I/O ermöglicht die Bearbeitung mehr konventioneller Anfragen.

    • Reaktionsfähigkeit *- Der Webserver bleibt während der großen Dateiverarbeitung reagierend.
    • Ressourceneffizienz*- Die Bedrohungen werden freigelassen, während sie auf I/O Operationen warten.

Voraussetzungen: Umwelt vorbereiten

  • Installieren Sie Visual Studio oder eine kompatible .NET IDE.
  • Erstellen Sie ein neues ASP.NET Core Web API-Projekt mit dem Ziel .NET 8.
  • Installieren Sie Aspose.Medical vom NuGet Package Manager.

Schritt für Schritt Guide zur Async DICOM JSON Serialisierung

Schritt 1: Installieren Aspose.Medical

Fügen Sie die Aspose.Medical Bibliothek zu Ihrem Projekt mit NuGet hinzu.

Install-Package Aspose.Medical

Schritt 2: Inkludieren Sie notwendige Namenräume

Fügen Sie Referenzen zu den erforderlichen Namenräumen in Ihrem Controller hinzu.

using Aspose.Medical.Dicom;
using Aspose.Medical.Dicom.Serialization;
using Microsoft.AspNetCore.Mvc;

Schritt 3: Erstellen von Async Deserialization Endpoint

Erstellen Sie einen Endpunkt, der JSON vom Antragsorgan deserialisiert.

[HttpPost("import")]
public async Task<IActionResult> ImportDicomJson()
{
    Dataset? dataset = await DicomJsonSerializer.DeserializeAsync(Request.Body);
    
    if (dataset == null)
        return BadRequest("Invalid DICOM JSON");
    
    return Ok("DICOM data imported successfully");
}

Schritt 4: Erstellen von Async Serialization Endpoint

Erstellen Sie einen Endpunkt, der DICOM zu JSON in der Antwort serialisiert.

[HttpGet("export/{filename}")]
public async Task ExportDicomJson(string filename)
{
    DicomFile dcm = DicomFile.Open($"storage/{filename}");
    
    Response.ContentType = "application/json";
    await DicomJsonSerializer.SerializeAsync(Response.Body, dcm.Dataset);
}

Schritt 5: Handeln Sie mit Cancellation Tokens

Pass cancelation tokens für die ordnungsgemäße request-annulation-behandlung.

[HttpPost("process")]
public async Task<IActionResult> ProcessDicomAsync(CancellationToken cancellationToken)
{
    Dataset? dataset = await DicomJsonSerializer.DeserializeAsync(
        Request.Body, 
        cancellationToken
    );
    
    if (cancellationToken.IsCancellationRequested)
        return StatusCode(499, "Client Closed Request");
    
    // Process dataset...
    return Ok();
}

Komplette ASP.NET Core Controller Vorlage

Hier ist ein vollständiger Controller, der Async DICOM JSON Operationen implementiert:

using Aspose.Medical.Dicom;
using Aspose.Medical.Dicom.Serialization;
using Microsoft.AspNetCore.Mvc;

namespace DicomApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class DicomController : ControllerBase
{
    private readonly string _storagePath = "dicom_storage";

    public DicomController()
    {
        Directory.CreateDirectory(_storagePath);
    }

    /// <summary>
    /// Import DICOM JSON and save as DICOM file
    /// </summary>
    [HttpPost("import")]
    public async Task<IActionResult> ImportDicomJson(CancellationToken cancellationToken)
    {
        try
        {
            Dataset? dataset = await DicomJsonSerializer.DeserializeAsync(
                Request.Body, 
                cancellationToken
            );

            if (dataset == null)
                return BadRequest("Failed to deserialize DICOM JSON");

            // Generate unique filename
            string filename = $"{Guid.NewGuid()}.dcm";
            string filepath = Path.Combine(_storagePath, filename);

            // Save as DICOM file
            DicomFile dcm = new DicomFile(dataset);
            dcm.Save(filepath);

            return Ok(new { message = "DICOM imported successfully", filename });
        }
        catch (OperationCanceledException)
        {
            return StatusCode(499, "Request cancelled");
        }
        catch (Exception ex)
        {
            return BadRequest($"Import failed: {ex.Message}");
        }
    }

    /// <summary>
    /// Export DICOM file as JSON stream
    /// </summary>
    [HttpGet("export/{filename}")]
    public async Task ExportDicomJson(string filename, CancellationToken cancellationToken)
    {
        string filepath = Path.Combine(_storagePath, filename);

        if (!System.IO.File.Exists(filepath))
        {
            Response.StatusCode = 404;
            await Response.WriteAsync("File not found");
            return;
        }

        try
        {
            DicomFile dcm = DicomFile.Open(filepath);
            
            Response.ContentType = "application/json";
            Response.Headers["Content-Disposition"] = $"attachment; filename=\"{filename}.json\"";
            
            await DicomJsonSerializer.SerializeAsync(
                Response.Body, 
                dcm.Dataset, 
                writeIndented: true
            );
        }
        catch (OperationCanceledException)
        {
            // Client disconnected
        }
        catch (Exception ex)
        {
            Response.StatusCode = 500;
            await Response.WriteAsync($"Export failed: {ex.Message}");
        }
    }

    /// <summary>
    /// Convert uploaded DICOM file to JSON
    /// </summary>
    [HttpPost("convert")]
    [RequestSizeLimit(100_000_000)] // 100MB limit
    public async Task ConvertDicomToJson(IFormFile file, CancellationToken cancellationToken)
    {
        if (file == null || file.Length == 0)
        {
            Response.StatusCode = 400;
            await Response.WriteAsync("No file uploaded");
            return;
        }

        try
        {
            // Save uploaded file temporarily
            string tempPath = Path.GetTempFileName();
            using (var stream = System.IO.File.Create(tempPath))
            {
                await file.CopyToAsync(stream, cancellationToken);
            }

            // Load and convert
            DicomFile dcm = DicomFile.Open(tempPath);
            
            Response.ContentType = "application/json";
            await DicomJsonSerializer.SerializeAsync(
                Response.Body, 
                dcm.Dataset, 
                writeIndented: true
            );

            // Cleanup temp file
            System.IO.File.Delete(tempPath);
        }
        catch (OperationCanceledException)
        {
            // Client disconnected
        }
        catch (Exception ex)
        {
            Response.StatusCode = 500;
            await Response.WriteAsync($"Conversion failed: {ex.Message}");
        }
    }
}

Konfiguration der Anfrage Größe Grenzen

Für große DICOM-Dateien konfigurieren Sie die Anfragegrenze in Program.cs:

var builder = WebApplication.CreateBuilder(args);

// Configure Kestrel for large uploads
builder.WebHost.ConfigureKestrel(options =>
{
    options.Limits.MaxRequestBodySize = 500_000_000; // 500MB
});

// Configure form options
builder.Services.Configure<FormOptions>(options =>
{
    options.MultipartBodyLengthLimit = 500_000_000;
});

var app = builder.Build();

Streamverarbeitung zum Beispiel

Verarbeiten Sie DICOM-Dateien ohne vollständig in das Gedächtnis zu laden:

[HttpPost("stream-process")]
public async Task StreamProcessDicom(CancellationToken cancellationToken)
{
    // Read JSON from request body stream
    using var reader = new StreamReader(Request.Body);
    string json = await reader.ReadToEndAsync(cancellationToken);
    
    // Deserialize
    Dataset? dataset = DicomJsonSerializer.Deserialize(json);
    
    if (dataset == null)
    {
        Response.StatusCode = 400;
        await Response.WriteAsync("Invalid JSON");
        return;
    }
    
    // Process and stream response
    Response.ContentType = "application/json";
    await DicomJsonSerializer.SerializeAsync(
        Response.Body, 
        dataset, 
        writeIndented: true
    );
}

Fehlerbehandlung Best Practices

Implementieren umfassender Fehlerbehandlung:

[HttpPost("safe-import")]
public async Task<IActionResult> SafeImportDicomJson(CancellationToken cancellationToken)
{
    try
    {
        Dataset? dataset = await DicomJsonSerializer.DeserializeAsync(
            Request.Body, 
            cancellationToken
        );

        if (dataset == null)
            return BadRequest(new { error = "Invalid DICOM JSON format" });

        // Process dataset...
        return Ok(new { success = true });
    }
    catch (OperationCanceledException)
    {
        return StatusCode(499, new { error = "Request cancelled by client" });
    }
    catch (JsonException ex)
    {
        return BadRequest(new { error = "JSON parsing error", details = ex.Message });
    }
    catch (OutOfMemoryException)
    {
        return StatusCode(507, new { error = "File too large to process" });
    }
    catch (Exception ex)
    {
        return StatusCode(500, new { error = "Internal server error", details = ex.Message });
    }
}

Weitere Best Practices

Verwendung von Erklärungen für Streams

Verwenden Sie immer die richtigen Ausrüstungsmuster:

using (FileStream fs = System.IO.File.OpenRead(filepath))
{
    // Process stream
}

Timeout Konfiguration

Konfigurieren Sie geeignete Zeiträume für lange Operationen:

builder.WebHost.ConfigureKestrel(options =>
{
    options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(2);
    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(5);
});

Zusätzliche Informationen

  • Async-Methoden verbessern die Skalierbarkeit, beschleunigen jedoch nicht unbedingt individuelle Anfragen.
  • Verwenden Sie Cancellation-Token, um Client-Diskonnektionen ordnungsgemäß zu handhaben.
  • Überwachen Sie die Speicherverwendung bei der Verarbeitung von großen DICOM-Dateien.

Schlussfolgerungen

Dieses Tutorial hat gezeigt, wie man Async DICOM JSON-Serialisierung in ASP.NET Core Web APIs mit Aspose.Medical implementiert.Asynch-Operationen sind unerlässlich für den Aufbau skalierbarer Gesundheits-APIs, die große medizinische Imaging-Daten effizient verarbeiten.

 Deutsch