Zum Fußzeileninhalt springen
VIDEOS

Wie man OCR in C# mit Open-Source-Bibliotheken implementiert

Dieser Leitfaden richtet sich an .NET Entwickler, die die REST-API von Klippa integriert haben und nun für die lokale Dokumentenverarbeitung auf IronOCR umsteigen. Es umfasst die praktischen Schritte zur Entfernung der HTTP-Client-Infrastruktur, zur Eliminierung der JSON-Deserialisierung und zum Ersatz cloudabhängiger Dokumenten-Uploads durch lokale OCR-Aufrufe, die niemals das Netzwerk berühren.

Warum von Klippa OCRmigrieren?

Klippa ist ein reiner Cloud-basierter Dokumentenanalysedienst ohne .NET SDK. Jede Integration ist ein handgefertigter REST-Client. Diese architektonische Realität hat nachgelagerte Konsequenzen, die sich im Laufe der Lebensdauer eines Produktionssystems verstärken.

Kein NuGet Paket bedeutet, dass Sie die Integrationsschicht besitzen. Es muss nichts installiert werden. Die Einstiegskosten bestehen darin, einen HttpClient Wrapper zu schreiben, X-Auth-Key Authentifizierungs-Header zu konfigurieren, MultipartFormDataContent Anforderungsinhalte zu erstellen, Klippas JSON-Antwortschema zu deserialisieren und Wiederholungslogik für vorübergehende Fehler zu verknüpfen. Das bedeutet 2-4 Tage Vorbereitungszeit, bevor das erste Dokument zuverlässig in der Produktion verarbeitet werden kann. Wenn Klippa sein API-Schema aktualisiert, funktioniert Ihr Deserialisierungscode nicht mehr und muss manuell gewartet werden.

Jeder Dokumenten-Upload ist netzwerkabhängig. Klippa verarbeitet Dokumente ausschließlich auf Servern in der EU. Produktionsausfälle auf Seiten von Klippa, erhöhte Latenz oder jegliche Unterbrechung des ausgehenden Internetzugangs von Ihrem Anwendungsserver führen zu einem vollständigen Stopp der Dokumentenverarbeitung. Es gibt keinen Ausweichmechanismus, keinen lokalen Modus und keine Wiederholungsmöglichkeit, um das Problem der Nichtverfügbarkeit eines Cloud-Dienstes zu beheben.

Sensible Dokumente verlassen Ihre Infrastruktur. Finanzdokumente – Quittungen mit Zahlungsdetails, Rechnungen mit Umsatzsteuer-Identifikationsnummern und Beträgen, Ausweisdokumente mit Passdaten – werden bei jedem API-Aufruf an einen Server eines Drittanbieters übermittelt. Die Bestimmungen der DSGVO zur Datenübertragung regeln einige dieser Punkte für die Verarbeitung innerhalb der EU, der Prüfungsbereich erstreckt sich jedoch weiterhin auf die Infrastruktur von Klippa, die Richtlinien zur Datenaufbewahrung und die Unterauftragnehmer. Für Teams mit Verträgen im Gesundheitswesen, im Rechtswesen, im Finanzdienstleistungssektor oder im öffentlichen Sektor genügt die Angabe "EU-gehostet" nicht der Anforderung, dass die Daten das Unternehmen nicht verlassen dürfen.

Die Preise pro Dokument sind nach oben offen. Klippa veröffentlicht keine Preise. Bei einem nennenswerten Dokumentenvolumen – 10.000 Belege pro Monat in einem Spesenmanagementsystem, 500 Rechnungen pro Tag in einem automatisierten Kreditorenbuchhaltungs-Workflow – entstehen bei dem Abrechnungsmodell pro Dokument Kosten, die bei einer unbefristeten Lizenz niemals anfallen würden. Die Kostenentwicklung ist direkt an das Unternehmenswachstum gekoppelt, was genau das Gegenteil dessen ist, was Infrastrukturausgaben bewirken sollten.

Der Spezialisierungsbereich stößt an seine Grenzen, wenn die Anforderungen steigen. Klippa ist in der Bearbeitung von Quittungen, Rechnungen und Ausweisdokumenten geschult. Eine Anwendung, die als Spesenmanagement-Anwendung beginnt, bleibt selten dabei. Beim ersten Auftreten eines Dokumenttyps außerhalb dieser drei Kategorien – beispielsweise eines eingescannten Arbeitsvertrags, eines medizinischen Formulars, einer technischen Zeichnung oder einer Bestellung mit nicht standardmäßigem Layout – liefert Klippa keine brauchbaren Ergebnisse.IronOCR verarbeitet jedes Dokument, das Text enthält, ohne Kategorienbeschränkungen.

Asynchrone REST-Aufrufe führen in synchronen Kontexten zu Latenz. Jeder Klippa-Aufruf ist eine asynchrone HTTP-Operation. Die Übertragung eines einzelnen Dokuments über das Netzwerk dauert 500 ms bis 2000 ms.IronOCR verarbeitet dasselbe Dokument lokal in 100-400 ms ohne den asynchronen Overhead in Szenarien, in denen die synchrone Verarbeitung besser zur Architektur passt.

Das grundsätzliche Problem

Klippa hat kein SDK. OCR bedeutet, eine HTTP-Anfrage zu erstellen und zu senden und anschließend JSON zu deserialisieren:

// Klippa: 15+ lines of HTTP plumbing before you read a single character
var content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(File.ReadAllBytes(imagePath)), "document", "receipt.jpg");
_client.DefaultRequestHeaders.Add("X-Auth-Key", _apiKey); // auth header — rotates, breaks, leaks

var response = await _client.PostAsync(
    "https://custom-ocr.klippa.com/api/v1/parseDocument", content);
response.EnsureSuccessStatusCode(); // throws on 4xx/5xx — no retry, document lost

var json = await response.Content.ReadAsStringAsync();
var parsed = JsonSerializer.Deserialize<KlippaResponse>(json); // your schema, your maintenance
var text = parsed?.Data?.ParsedDocument?.Text; // nullable chain — breaks when schema changes
// Klippa: 15+ lines of HTTP plumbing before you read a single character
var content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(File.ReadAllBytes(imagePath)), "document", "receipt.jpg");
_client.DefaultRequestHeaders.Add("X-Auth-Key", _apiKey); // auth header — rotates, breaks, leaks

var response = await _client.PostAsync(
    "https://custom-ocr.klippa.com/api/v1/parseDocument", content);
response.EnsureSuccessStatusCode(); // throws on 4xx/5xx — no retry, document lost

var json = await response.Content.ReadAsStringAsync();
var parsed = JsonSerializer.Deserialize<KlippaResponse>(json); // your schema, your maintenance
var text = parsed?.Data?.ParsedDocument?.Text; // nullable chain — breaks when schema changes
Imports System.Net.Http
Imports System.IO
Imports System.Text.Json
Imports System.Threading.Tasks

' Klippa: 15+ lines of HTTP plumbing before you read a single character
Dim content As New MultipartFormDataContent()
content.Add(New ByteArrayContent(File.ReadAllBytes(imagePath)), "document", "receipt.jpg")
_client.DefaultRequestHeaders.Add("X-Auth-Key", _apiKey) ' auth header — rotates, breaks, leaks

Dim response As HttpResponseMessage = Await _client.PostAsync("https://custom-ocr.klippa.com/api/v1/parseDocument", content)
response.EnsureSuccessStatusCode() ' throws on 4xx/5xx — no retry, document lost

Dim json As String = Await response.Content.ReadAsStringAsync()
Dim parsed As KlippaResponse = JsonSerializer.Deserialize(Of KlippaResponse)(json) ' your schema, your maintenance
Dim text As String = parsed?.Data?.ParsedDocument?.Text ' nullable chain — breaks when schema changes
$vbLabelText   $csharpLabel

IronOCR ersetzt das alles:

// IronOCR: no HTTP, no auth headers, no JSON — just text
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read(imagePath).Text;
// IronOCR: no HTTP, no auth headers, no JSON — just text
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read(imagePath).Text;
' IronOCR: no HTTP, no auth headers, no JSON — just text
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim text = New IronTesseract().Read(imagePath).Text
$vbLabelText   $csharpLabel

IronOCR vs. Klippa OCR: Funktionsvergleich

Die folgende Tabelle vergleicht die beiden Bibliotheken hinsichtlich der Dimensionen, die für eine Entscheidung zur Produktionsmigration am wichtigsten sind.

Feature Klippa OCR IronOCR
Bereitstellungsmodell Cloud-only (EU-Server) Vor Ort, vollständig lokal
.NET SDK / NuGet -Paket None IronOcr NuGet-Paket
Internet erforderlich Ja, bei jedem Anruf. Niemals
Dokumentdaten verlassen das Netzwerk Stets Niemals
Allgemeine OCR Nein (nur Quittungen, Rechnungen, Ausweise) Ja (jeder Dokumenttyp)
Authentifizierungseinrichtung X-Auth-Key HTTP-Header IronOcr.License.LicenseKey string
HTTP-Client erforderlich Ja Nein
Antwortdeserialisierung Manuelles JSON-Parsing Getiptes OcrResult Objekt
Wiederholungs-/Timeout-Logik Handgerollt Nicht erforderlich (Ortsgespräch)
Offline-/Air-Gap-Unterstützung Nein Ja
PDF-Eingabe Ja (Wolke) Ja (einheimisch, lokal)
Mehrseitige TIFF-Eingabe Unbekannt Ja
Bildeingabeformate JPG, PNG (Wolke) JPG, PNG, BMP, TIFF, GIF und mehr
Eingabe von Datenströmen und Byte-Arrays Kein SDK Ja
Automatische Bildvorverarbeitung Wolkenseite (undurchsichtig) Ja (Entzerren, Rauschen entfernen, Kontrast, Binarisieren, Schärfen)
Strukturierte Ausgabe: Wortkoordinaten Nein Ja
Konfidenzwerte pro Wort Nein Ja
Durchsuchbare PDF-Ausgabe Nein Ja
Barcode-Lesung während der OCR Nein Ja
Mehrsprachige Unterstützung Beschränkt auf geschulte Dokumententypen 125+ Sprachen
Gewindesicherheit Nicht verfügbar (HTTP-Anrufe) Ja (ein IronTesseract pro Thread)
Plattformübergreifende Bereitstellung REST-agnostisch Windows, Linux, macOS, Docker, Azure, AWS
HIPAA-/ITAR-/Air-Gap-Konformität Nein Ja
Preismodell SaaS pro Dokument (nicht veröffentlichte Preise) Unbefristete Lizenz von $999
Kosten pro Seite bei entsprechender Größenordnung Ja, grenzenlos None

Schnellstart: Migration von Klippa OCRzu IronOCR

Schritt 1: Ersetzen des NuGet-Pakets

Für Klippa gibt es kein offizielles NuGet Paket. Entfernen Sie die HTTP-Client-Abhängigkeiten, die ausschließlich zur Unterstützung der Klippa-Integration existieren:

# Remove Klippa-related packages (if installed for REST support)
dotnet remove package Newtonsoft.Json
dotnet remove package System.Net.Http.Json
# Remove Klippa-related packages (if installed for REST support)
dotnet remove package Newtonsoft.Json
dotnet remove package System.Net.Http.Json
SHELL

Installieren Sie IronOCR über NuGet :

dotnet add package IronOcr

Schritt 2: Namespaces aktualisieren

Entfernen Sie die HTTP- und JSON-Namensräume, die für die Klippa-Integration erforderlich waren. Fügen Sie den einzelnen IronOCR Namespace hinzu:

// Before (Klippa integration)
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Text.Json.Serialization;

// After (IronOCR)
using IronOcr;
// Before (Klippa integration)
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Text.Json.Serialization;

// After (IronOCR)
using IronOcr;
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Text.Json
Imports System.Text.Json.Serialization

Imports IronOcr
$vbLabelText   $csharpLabel

Schritt 3: Lizenz initialisieren

Fügen Sie die Lizenzinitialisierung einmal beim Anwendungsstart hinzu — in Program.cs, Startup.cs oder vor dem ersten OCR-Aufruf:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Beispiele für die Code-Migration

Ersetzen der HTTP-Client-Dienstklasse

Die Klippa-Integration erfordert eine vollständige Serviceklasse, die die HTTP-Infrastruktur umschließt. Das lässt sich nicht vermeiden, da es kein SDK gibt.

Klippa-Ansatz:

// Klippa: entire service class just to send one HTTP request
public class KlippaOcrService : IDisposable
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl = "https://custom-ocr.klippa.com/api/v1";

    public KlippaOcrService(string apiKey)
    {
        _httpClient = new HttpClient();
        _httpClient.DefaultRequestHeaders.Add("X-Auth-Key", apiKey);
        _httpClient.Timeout = TimeSpan.FromSeconds(30); // network timeout required
    }

    public async Task<string> ReadDocumentTextAsync(string filePath)
    {
        using var form = new MultipartFormDataContent();
        var fileBytes = await File.ReadAllBytesAsync(filePath);
        form.Add(new ByteArrayContent(fileBytes), "document", Path.GetFileName(filePath));

        var response = await _httpClient.PostAsync($"{_baseUrl}/parseDocument", form);
        response.EnsureSuccessStatusCode();

        var json = await response.Content.ReadAsStringAsync();
        using var doc = JsonDocument.Parse(json);
        // navigate Klippa's nested JSON schema
        return doc.RootElement
            .GetProperty("data")
            .GetProperty("parsed_document")
            .GetProperty("text")
            .GetString() ?? string.Empty;
    }

    public void Dispose() => _httpClient.Dispose();
}
// Klippa: entire service class just to send one HTTP request
public class KlippaOcrService : IDisposable
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl = "https://custom-ocr.klippa.com/api/v1";

    public KlippaOcrService(string apiKey)
    {
        _httpClient = new HttpClient();
        _httpClient.DefaultRequestHeaders.Add("X-Auth-Key", apiKey);
        _httpClient.Timeout = TimeSpan.FromSeconds(30); // network timeout required
    }

    public async Task<string> ReadDocumentTextAsync(string filePath)
    {
        using var form = new MultipartFormDataContent();
        var fileBytes = await File.ReadAllBytesAsync(filePath);
        form.Add(new ByteArrayContent(fileBytes), "document", Path.GetFileName(filePath));

        var response = await _httpClient.PostAsync($"{_baseUrl}/parseDocument", form);
        response.EnsureSuccessStatusCode();

        var json = await response.Content.ReadAsStringAsync();
        using var doc = JsonDocument.Parse(json);
        // navigate Klippa's nested JSON schema
        return doc.RootElement
            .GetProperty("data")
            .GetProperty("parsed_document")
            .GetProperty("text")
            .GetString() ?? string.Empty;
    }

    public void Dispose() => _httpClient.Dispose();
}
Imports System
Imports System.IO
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.Text.Json

' Klippa: entire service class just to send one HTTP request
Public Class KlippaOcrService
    Implements IDisposable

    Private ReadOnly _httpClient As HttpClient
    Private ReadOnly _baseUrl As String = "https://custom-ocr.klippa.com/api/v1"

    Public Sub New(apiKey As String)
        _httpClient = New HttpClient()
        _httpClient.DefaultRequestHeaders.Add("X-Auth-Key", apiKey)
        _httpClient.Timeout = TimeSpan.FromSeconds(30) ' network timeout required
    End Sub

    Public Async Function ReadDocumentTextAsync(filePath As String) As Task(Of String)
        Using form As New MultipartFormDataContent()
            Dim fileBytes = Await File.ReadAllBytesAsync(filePath)
            form.Add(New ByteArrayContent(fileBytes), "document", Path.GetFileName(filePath))

            Dim response = Await _httpClient.PostAsync($"{_baseUrl}/parseDocument", form)
            response.EnsureSuccessStatusCode()

            Dim json = Await response.Content.ReadAsStringAsync()
            Using doc = JsonDocument.Parse(json)
                ' navigate Klippa's nested JSON schema
                Return doc.RootElement _
                    .GetProperty("data") _
                    .GetProperty("parsed_document") _
                    .GetProperty("text") _
                    .GetString() OrElse String.Empty
            End Using
        End Using
    End Function

    Public Sub Dispose() Implements IDisposable.Dispose
        _httpClient.Dispose()
    End Sub
End Class
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// IronOCR: no HTTP, no JSON navigation, no Dispose plumbing
public class OcrService
{
    private readonly IronTesseract _ocr = new IronTesseract();

    public string ReadDocumentText(string filePath)
    {
        return _ocr.Read(filePath).Text;
    }
}

// At startup:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Usage — identical call site, different internals:
var service = new OcrService();
var text = service.ReadDocumentText("invoice.jpg"); // local, synchronous, zero network
// IronOCR: no HTTP, no JSON navigation, no Dispose plumbing
public class OcrService
{
    private readonly IronTesseract _ocr = new IronTesseract();

    public string ReadDocumentText(string filePath)
    {
        return _ocr.Read(filePath).Text;
    }
}

// At startup:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Usage — identical call site, different internals:
var service = new OcrService();
var text = service.ReadDocumentText("invoice.jpg"); // local, synchronous, zero network
Imports IronOcr

Public Class OcrService
    Private ReadOnly _ocr As New IronTesseract()

    Public Function ReadDocumentText(filePath As String) As String
        Return _ocr.Read(filePath).Text
    End Function
End Class

' At startup:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

' Usage — identical call site, different internals:
Dim service As New OcrService()
Dim text As String = service.ReadDocumentText("invoice.jpg") ' local, synchronous, zero network
$vbLabelText   $csharpLabel

Die Klippa-Serviceklasse existiert ausschließlich deshalb, weil die API eine HTTP-Infrastruktur benötigt. Das IronOCR-Äquivalent reduziert sich auf einen einzigen Read() Aufruf. Timeouts, Authentifizierungs-Header und Entsorgungsmuster verschwinden alle, weil kein Netzwerk vorhanden ist. Informationen zu den Initialisierungsoptionen finden Sie im IronTesseract-Setup-Leitfaden und einen funktionierenden Code im einfachen OCR-Beispiel .

Eliminierung des Uploads von mehrteiligen Formularen

Klippa empfängt Dokumente als mehrteilige Formular-Uploads. Der Upload-Code ist mechanisch, aber fehleranfällig: Dateilesen, Content-Type-Header, Begrenzungskonstruktion und Upload-Größenverwaltung.

Klippa-Ansatz:

// Klippa: multipart upload — every document is an HTTP form POST
public async Task<KlippaResult> UploadAndParseAsync(
    string filePath, string documentType = "financial")
{
    using var form = new MultipartFormDataContent();

    // read file into memory — entire document in RAM before upload
    var fileBytes = await File.ReadAllBytesAsync(filePath);
    var byteContent = new ByteArrayContent(fileBytes);
    byteContent.Headers.ContentType =
        new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");

    form.Add(byteContent, "document", Path.GetFileName(filePath));
    form.Add(new StringContent(documentType), "DocumentType");

    // document leaves your server here
    var response = await _httpClient.PostAsync(
        "https://custom-ocr.klippa.com/api/v1/parseDocument", form);

    if (!response.IsSuccessStatusCode)
    {
        var error = await response.Content.ReadAsStringAsync();
        throw new InvalidOperationException($"Klippa API error: {response.StatusCode} — {error}");
    }

    var json = await response.Content.ReadAsStringAsync();
    return JsonSerializer.Deserialize<KlippaResult>(json,
        new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
}
// Klippa: multipart upload — every document is an HTTP form POST
public async Task<KlippaResult> UploadAndParseAsync(
    string filePath, string documentType = "financial")
{
    using var form = new MultipartFormDataContent();

    // read file into memory — entire document in RAM before upload
    var fileBytes = await File.ReadAllBytesAsync(filePath);
    var byteContent = new ByteArrayContent(fileBytes);
    byteContent.Headers.ContentType =
        new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");

    form.Add(byteContent, "document", Path.GetFileName(filePath));
    form.Add(new StringContent(documentType), "DocumentType");

    // document leaves your server here
    var response = await _httpClient.PostAsync(
        "https://custom-ocr.klippa.com/api/v1/parseDocument", form);

    if (!response.IsSuccessStatusCode)
    {
        var error = await response.Content.ReadAsStringAsync();
        throw new InvalidOperationException($"Klippa API error: {response.StatusCode} — {error}");
    }

    var json = await response.Content.ReadAsStringAsync();
    return JsonSerializer.Deserialize<KlippaResult>(json,
        new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
}
Imports System.IO
Imports System.Net.Http
Imports System.Text.Json
Imports System.Threading.Tasks

Public Class KlippaUploader
    Private ReadOnly _httpClient As HttpClient

    Public Sub New(httpClient As HttpClient)
        _httpClient = httpClient
    End Sub

    Public Async Function UploadAndParseAsync(filePath As String, Optional documentType As String = "financial") As Task(Of KlippaResult)
        Using form As New MultipartFormDataContent()
            ' read file into memory — entire document in RAM before upload
            Dim fileBytes = Await File.ReadAllBytesAsync(filePath)
            Dim byteContent = New ByteArrayContent(fileBytes)
            byteContent.Headers.ContentType = New System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg")

            form.Add(byteContent, "document", Path.GetFileName(filePath))
            form.Add(New StringContent(documentType), "DocumentType")

            ' document leaves your server here
            Dim response = Await _httpClient.PostAsync("https://custom-ocr.klippa.com/api/v1/parseDocument", form)

            If Not response.IsSuccessStatusCode Then
                Dim error = Await response.Content.ReadAsStringAsync()
                Throw New InvalidOperationException($"Klippa API error: {response.StatusCode} — {error}")
            End If

            Dim json = Await response.Content.ReadAsStringAsync()
            Return JsonSerializer.Deserialize(Of KlippaResult)(json, New JsonSerializerOptions With {.PropertyNameCaseInsensitive = True})
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// IronOCR: load from file path, byte array, or stream — no upload, no form
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// From file path
using var input = new OcrInput();
input.LoadImage("invoice.jpg");
var result = new IronTesseract().Read(input);

// From byte array (same bytes Klippa was uploading)
byte[] fileBytes = await File.ReadAllBytesAsync("invoice.jpg");
using var inputFromBytes = new OcrInput();
inputFromBytes.LoadImage(fileBytes);
var resultFromBytes = new IronTesseract().Read(inputFromBytes);

Console.WriteLine(result.Text);
// IronOCR: load from file path, byte array, or stream — no upload, no form
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// From file path
using var input = new OcrInput();
input.LoadImage("invoice.jpg");
var result = new IronTesseract().Read(input);

// From byte array (same bytes Klippa was uploading)
byte[] fileBytes = await File.ReadAllBytesAsync("invoice.jpg");
using var inputFromBytes = new OcrInput();
inputFromBytes.LoadImage(fileBytes);
var resultFromBytes = new IronTesseract().Read(inputFromBytes);

Console.WriteLine(result.Text);
Imports IronOcr
Imports System.IO

' IronOCR: load from file path, byte array, or stream — no upload, no form
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

' From file path
Using input As New OcrInput()
    input.LoadImage("invoice.jpg")
    Dim result = New IronTesseract().Read(input)

    ' From byte array (same bytes Klippa was uploading)
    Dim fileBytes As Byte() = Await File.ReadAllBytesAsync("invoice.jpg")
    Using inputFromBytes As New OcrInput()
        inputFromBytes.LoadImage(fileBytes)
        Dim resultFromBytes = New IronTesseract().Read(inputFromBytes)

        Console.WriteLine(result.Text)
    End Using
End Using
$vbLabelText   $csharpLabel

Die MultipartFormDataContent-Konstruktion, Inhaltstyp-Header und der Upload selbst sind alle verschwunden.IronOCR liest direkt aus dem Dateipfad, aus einem Byte-Array oder aus einem Stream — die gleichen Daten, die Klippa in die Cloud übermittelte, bleiben lokal. Der Leitfaden zur Bildeingabe behandelt alle unterstützten Eingabeformate, und der Leitfaden zur Stream-Eingabe behandelt den Speicher-Stream-Pfad für Dokumente, die als Byte-Arrays von vorgelagerten Prozessen eintreffen.

Ersetzen der Deserialisierung von JSON-Antworten

Klippa gibt eine verschachtelte JSON-Struktur zurück. Die Navigation in dieser Struktur erfordert entweder ein entsprechendes C#-Modell oder eine Inline-JsonDocument-Durchquerung — beides bricht, wenn Klippa ihr Antwortschema ändert.

Klippa-Ansatz:

// Klippa: deserialization model — breaks when API schema changes
public class KlippaResponse
{
    [JsonPropertyName("data")]
    public KlippaData Data { get; set; }
}

public class KlippaData
{
    [JsonPropertyName("parsed_document")]
    public KlippaParsedDocument ParsedDocument { get; set; }
}

public class KlippaParsedDocument
{
    [JsonPropertyName("text")]
    public string Text { get; set; }

    [JsonPropertyName("amount")]
    public decimal? Amount { get; set; }

    [JsonPropertyName("merchant")]
    public string Merchant { get; set; }

    [JsonPropertyName("date")]
    public string Date { get; set; }
}

// Usage: navigate the nullable chain every time
public async Task<string> GetExtractedTextAsync(string imagePath)
{
    var klippaResult = await UploadAndParseAsync(imagePath);
    // every property access is nullable — schema drift breaks this silently
    return klippaResult?.Data?.ParsedDocument?.Text ?? string.Empty;
}
// Klippa: deserialization model — breaks when API schema changes
public class KlippaResponse
{
    [JsonPropertyName("data")]
    public KlippaData Data { get; set; }
}

public class KlippaData
{
    [JsonPropertyName("parsed_document")]
    public KlippaParsedDocument ParsedDocument { get; set; }
}

public class KlippaParsedDocument
{
    [JsonPropertyName("text")]
    public string Text { get; set; }

    [JsonPropertyName("amount")]
    public decimal? Amount { get; set; }

    [JsonPropertyName("merchant")]
    public string Merchant { get; set; }

    [JsonPropertyName("date")]
    public string Date { get; set; }
}

// Usage: navigate the nullable chain every time
public async Task<string> GetExtractedTextAsync(string imagePath)
{
    var klippaResult = await UploadAndParseAsync(imagePath);
    // every property access is nullable — schema drift breaks this silently
    return klippaResult?.Data?.ParsedDocument?.Text ?? string.Empty;
}
Imports System.Text.Json.Serialization

' Klippa: deserialization model — breaks when API schema changes
Public Class KlippaResponse
    <JsonPropertyName("data")>
    Public Property Data As KlippaData
End Class

Public Class KlippaData
    <JsonPropertyName("parsed_document")>
    Public Property ParsedDocument As KlippaParsedDocument
End Class

Public Class KlippaParsedDocument
    <JsonPropertyName("text")>
    Public Property Text As String

    <JsonPropertyName("amount")>
    Public Property Amount As Decimal?

    <JsonPropertyName("merchant")>
    Public Property Merchant As String

    <JsonPropertyName("date")>
    Public Property Date As String
End Class

' Usage: navigate the nullable chain every time
Public Async Function GetExtractedTextAsync(imagePath As String) As Task(Of String)
    Dim klippaResult = Await UploadAndParseAsync(imagePath)
    ' every property access is nullable — schema drift breaks this silently
    Return If(klippaResult?.Data?.ParsedDocument?.Text, String.Empty)
End Function
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// IronOCR: typed result object — no JSON schema, no nullable chains
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

var ocr = new IronTesseract();
var result = ocr.Read("invoice.jpg");

// Direct property access — no deserialization, no nullable navigation
string fullText   = result.Text;
double confidence = result.Confidence;
int pageCount     = result.Pages.Count();

// Structured data: lines and words with coordinates
foreach (var page in result.Pages)
{
    foreach (var line in page.Lines)
    {
        Console.WriteLine($"Line: '{line.Text}' at Y={line.Y}");
    }
}
// IronOCR: typed result object — no JSON schema, no nullable chains
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

var ocr = new IronTesseract();
var result = ocr.Read("invoice.jpg");

// Direct property access — no deserialization, no nullable navigation
string fullText   = result.Text;
double confidence = result.Confidence;
int pageCount     = result.Pages.Count();

// Structured data: lines and words with coordinates
foreach (var page in result.Pages)
{
    foreach (var line in page.Lines)
    {
        Console.WriteLine($"Line: '{line.Text}' at Y={line.Y}");
    }
}
Imports IronOcr

' IronOCR: typed result object — no JSON schema, no nullable chains
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

Dim ocr As New IronTesseract()
Dim result = ocr.Read("invoice.jpg")

' Direct property access — no deserialization, no nullable navigation
Dim fullText As String = result.Text
Dim confidence As Double = result.Confidence
Dim pageCount As Integer = result.Pages.Count()

' Structured data: lines and words with coordinates
For Each page In result.Pages
    For Each line In page.Lines
        Console.WriteLine($"Line: '{line.Text}' at Y={line.Y}")
    Next
Next
$vbLabelText   $csharpLabel

OcrResult ist ein typisiertes .NET-Objekt. Es gibt kein JSON zu parsen, keine Modellklasse zu pflegen und kein Risiko, dass Schema-Drift die Deserialisierung in der Produktion beeinträchtigt. Der Leseergebnis-Leitfaden dokumentiert das vollständige OcrResult Objektmodell einschließlich Wortkoordinaten, Vertrauenswerten und strukturierter Seitenhierarchie. Für rechnungsspezifische Feldeextraktionsmuster, die auf OcrResult aufgebaut sind, behandelt das Rechnungs-OCR-Tutorial die End-to-End Extraktionslogik.

Entfernung der Fehlerbehandlungs- und Wiederholungsinfrastruktur

Die Integration von Klippa über HTTP erfordert eine Fehlerbehandlung für jeden Fehlermodus, der bei einem Netzwerkaufruf auftreten kann: Timeouts, 4xx-Antworten, 5xx-Antworten, Ratenbegrenzungen und partielles JSON. Teams, die Produktionsintegrationen durchführen, fügen Wiederholungsrichtlinien mithilfe von Polly oder benutzerdefinierter Logik hinzu. Diese Infrastruktur verschwindet, wenn der Netzwerkanruf abbricht.

Klippa-Ansatz:

// Klippa: retry policy required — cloud calls fail unpredictably
public async Task<string> ReadWithRetryAsync(string filePath, int maxRetries = 3)
{
    var delay = TimeSpan.FromSeconds(1);

    for (int attempt = 1; attempt <= maxRetries; attempt++)
    {
        try
        {
            using var form = new MultipartFormDataContent();
            form.Add(
                new ByteArrayContent(await File.ReadAllBytesAsync(filePath)),
                "document",
                Path.GetFileName(filePath));

            using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
            var response = await _httpClient.PostAsync(
                "https://custom-ocr.klippa.com/api/v1/parseDocument", form, cts.Token);

            if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
            {
                // rate limited — back off and retry
                await Task.Delay(delay * attempt);
                continue;
            }

            response.EnsureSuccessStatusCode();
            var json = await response.Content.ReadAsStringAsync(cts.Token);
            var parsed = JsonSerializer.Deserialize<KlippaResponse>(json);
            return parsed?.Data?.ParsedDocument?.Text ?? string.Empty;
        }
        catch (HttpRequestException) when (attempt < maxRetries)
        {
            await Task.Delay(delay * attempt); // exponential backoff
        }
        catch (TaskCanceledException) when (attempt < maxRetries)
        {
            await Task.Delay(delay * attempt); // timeout — retry
        }
    }

    throw new InvalidOperationException($"Klippa API failed after {maxRetries} attempts");
}
// Klippa: retry policy required — cloud calls fail unpredictably
public async Task<string> ReadWithRetryAsync(string filePath, int maxRetries = 3)
{
    var delay = TimeSpan.FromSeconds(1);

    for (int attempt = 1; attempt <= maxRetries; attempt++)
    {
        try
        {
            using var form = new MultipartFormDataContent();
            form.Add(
                new ByteArrayContent(await File.ReadAllBytesAsync(filePath)),
                "document",
                Path.GetFileName(filePath));

            using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
            var response = await _httpClient.PostAsync(
                "https://custom-ocr.klippa.com/api/v1/parseDocument", form, cts.Token);

            if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
            {
                // rate limited — back off and retry
                await Task.Delay(delay * attempt);
                continue;
            }

            response.EnsureSuccessStatusCode();
            var json = await response.Content.ReadAsStringAsync(cts.Token);
            var parsed = JsonSerializer.Deserialize<KlippaResponse>(json);
            return parsed?.Data?.ParsedDocument?.Text ?? string.Empty;
        }
        catch (HttpRequestException) when (attempt < maxRetries)
        {
            await Task.Delay(delay * attempt); // exponential backoff
        }
        catch (TaskCanceledException) when (attempt < maxRetries)
        {
            await Task.Delay(delay * attempt); // timeout — retry
        }
    }

    throw new InvalidOperationException($"Klippa API failed after {maxRetries} attempts");
}
Imports System
Imports System.IO
Imports System.Net.Http
Imports System.Text.Json
Imports System.Threading
Imports System.Threading.Tasks

Public Class KlippaService
    Private ReadOnly _httpClient As HttpClient

    Public Sub New(httpClient As HttpClient)
        _httpClient = httpClient
    End Sub

    ' Klippa: retry policy required — cloud calls fail unpredictably
    Public Async Function ReadWithRetryAsync(filePath As String, Optional maxRetries As Integer = 3) As Task(Of String)
        Dim delay As TimeSpan = TimeSpan.FromSeconds(1)

        For attempt As Integer = 1 To maxRetries
            Try
                Using form As New MultipartFormDataContent()
                    form.Add(New ByteArrayContent(Await File.ReadAllBytesAsync(filePath)), "document", Path.GetFileName(filePath))

                    Using cts As New CancellationTokenSource(TimeSpan.FromSeconds(30))
                        Dim response As HttpResponseMessage = Await _httpClient.PostAsync("https://custom-ocr.klippa.com/api/v1/parseDocument", form, cts.Token)

                        If response.StatusCode = System.Net.HttpStatusCode.TooManyRequests Then
                            ' rate limited — back off and retry
                            Await Task.Delay(delay * attempt)
                            Continue For
                        End If

                        response.EnsureSuccessStatusCode()
                        Dim json As String = Await response.Content.ReadAsStringAsync(cts.Token)
                        Dim parsed As KlippaResponse = JsonSerializer.Deserialize(Of KlippaResponse)(json)
                        Return If(parsed?.Data?.ParsedDocument?.Text, String.Empty)
                    End Using
                End Using
            Catch ex As HttpRequestException When attempt < maxRetries
                Await Task.Delay(delay * attempt) ' exponential backoff
            Catch ex As TaskCanceledException When attempt < maxRetries
                Await Task.Delay(delay * attempt) ' timeout — retry
            End Try
        Next

        Throw New InvalidOperationException($"Klippa API failed after {maxRetries} attempts")
    End Function
End Class

Public Class KlippaResponse
    Public Property Data As KlippaData
End Class

Public Class KlippaData
    Public Property ParsedDocument As ParsedDocument
End Class

Public Class ParsedDocument
    Public Property Text As String
End Class
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// IronOCR: no network, no retry policy needed — local call either works or throws once
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

public string ReadDocument(string filePath)
{
    //Neinretry loop.NeinCancellationTokenSource.NeinHTTP status checks.
    //Neinrate limit handling.Neinpartial-JSON guards.
    var result = new IronTesseract().Read(filePath);
    return result.Text;
}
// IronOCR: no network, no retry policy needed — local call either works or throws once
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

public string ReadDocument(string filePath)
{
    //Neinretry loop.NeinCancellationTokenSource.NeinHTTP status checks.
    //Neinrate limit handling.Neinpartial-JSON guards.
    var result = new IronTesseract().Read(filePath);
    return result.Text;
}
Imports IronOcr

' IronOCR: no network, no retry policy needed — local call either works or throws once
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

Public Function ReadDocument(filePath As String) As String
    ' Neinretry loop.NeinCancellationTokenSource.NeinHTTP status checks.
    ' Neinrate limit handling.Neinpartial-JSON guards.
    Dim result = New IronTesseract().Read(filePath)
    Return result.Text
End Function
$vbLabelText   $csharpLabel

Die gesamte Wiederholungsinfrastruktur — die Schleife, die Verzögerungsberechnung, das CancellationTokenSource, die Verzweigung des HTTP-Statuscodes, der TaskCanceledException-Fangblock — existiert ausschließlich netzwerkbedingt. Entfernt man den Netzwerkaufruf, verschwindet das ganze Problem. Ein lokaler OCR-Aufruf schlägt mit einer typisierten Ausnahme fehl, wenn die Eingabedatei fehlt oder unlesbar ist; andernfalls ist er erfolgreich. Der Leitfaden zur Geschwindigkeitsoptimierung beschreibt die Leistungsoptimierung von IronOCR, falls der Durchsatz nach der Migration ein Problem darstellt.

Verarbeitung mehrseitiger PDFs ohne Cloud-Upload

Klippa akzeptiert PDF-Uploads über den gleichen parseDocument-Endpunkt. Mehrseitige PDFs verlassen weiterhin Ihr Netzwerk.IronOCR liest PDFs nativ, direkt im Prozess, mit seitenweisem Zugriff auf die Ergebnisse.

Klippa-Ansatz:

// Klippa: PDF upload — entire document transmitted, results depend on cloud availability
public async Task<List<string>> ExtractPdfPagesAsync(string pdfPath)
{
    var pages = new List<string>();

    // Klippa parses the entire PDF server-side and returns combined results
    // You cannot control per-page processing or access raw page text
    using var form = new MultipartFormDataContent();
    form.Add(
        new ByteArrayContent(await File.ReadAllBytesAsync(pdfPath)),
        "document",
        Path.GetFileName(pdfPath));

    var response = await _httpClient.PostAsync(
        "https://custom-ocr.klippa.com/api/v1/parseDocument", form);
    response.EnsureSuccessStatusCode();

    var json = await response.Content.ReadAsStringAsync();
    var result = JsonSerializer.Deserialize<KlippaResponse>(json);
    // Klippa returns the combined parsed text — no per-page breakdown in basic API
    pages.Add(result?.Data?.ParsedDocument?.Text ?? string.Empty);

    return pages;
}
// Klippa: PDF upload — entire document transmitted, results depend on cloud availability
public async Task<List<string>> ExtractPdfPagesAsync(string pdfPath)
{
    var pages = new List<string>();

    // Klippa parses the entire PDF server-side and returns combined results
    // You cannot control per-page processing or access raw page text
    using var form = new MultipartFormDataContent();
    form.Add(
        new ByteArrayContent(await File.ReadAllBytesAsync(pdfPath)),
        "document",
        Path.GetFileName(pdfPath));

    var response = await _httpClient.PostAsync(
        "https://custom-ocr.klippa.com/api/v1/parseDocument", form);
    response.EnsureSuccessStatusCode();

    var json = await response.Content.ReadAsStringAsync();
    var result = JsonSerializer.Deserialize<KlippaResponse>(json);
    // Klippa returns the combined parsed text — no per-page breakdown in basic API
    pages.Add(result?.Data?.ParsedDocument?.Text ?? string.Empty);

    return pages;
}
Imports System.IO
Imports System.Net.Http
Imports System.Text.Json
Imports System.Threading.Tasks

Public Class PdfExtractor
    Private ReadOnly _httpClient As HttpClient

    Public Sub New(httpClient As HttpClient)
        _httpClient = httpClient
    End Sub

    ' Klippa: PDF upload — entire document transmitted, results depend on cloud availability
    Public Async Function ExtractPdfPagesAsync(pdfPath As String) As Task(Of List(Of String))
        Dim pages As New List(Of String)()

        ' Klippa parses the entire PDF server-side and returns combined results
        ' You cannot control per-page processing or access raw page text
        Using form As New MultipartFormDataContent()
            form.Add(New ByteArrayContent(Await File.ReadAllBytesAsync(pdfPath)), "document", Path.GetFileName(pdfPath))

            Dim response = Await _httpClient.PostAsync("https://custom-ocr.klippa.com/api/v1/parseDocument", form)
            response.EnsureSuccessStatusCode()

            Dim json = Await response.Content.ReadAsStringAsync()
            Dim result = JsonSerializer.Deserialize(Of KlippaResponse)(json)
            ' Klippa returns the combined parsed text — no per-page breakdown in basic API
            pages.Add(If(result?.Data?.ParsedDocument?.Text, String.Empty))
        End Using

        Return pages
    End Function
End Class

Public Class KlippaResponse
    Public Property Data As KlippaData
End Class

Public Class KlippaData
    Public Property ParsedDocument As ParsedDocument
End Class

Public Class ParsedDocument
    Public Property Text As String
End Class
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// IronOCR: native PDF OCR with per-page structured access — no upload
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

using var input = new OcrInput();
input.LoadPdf("multi-page-invoice.pdf"); // reads locally — no HTTP

var ocr = new IronTesseract();
var result = ocr.Read(input);

// Per-page access — not available from Klippa's combined response
foreach (var page in result.Pages)
{
    Console.WriteLine($"Page {page.PageNumber}: {page.Lines.Count()} lines");
    Console.WriteLine(page.Text);
}

// Or produce a searchable PDF from the scanned original
result.SaveAsSearchablePdf("searchable-output.pdf");
// IronOCR: native PDF OCR with per-page structured access — no upload
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

using var input = new OcrInput();
input.LoadPdf("multi-page-invoice.pdf"); // reads locally — no HTTP

var ocr = new IronTesseract();
var result = ocr.Read(input);

// Per-page access — not available from Klippa's combined response
foreach (var page in result.Pages)
{
    Console.WriteLine($"Page {page.PageNumber}: {page.Lines.Count()} lines");
    Console.WriteLine(page.Text);
}

// Or produce a searchable PDF from the scanned original
result.SaveAsSearchablePdf("searchable-output.pdf");
Imports IronOcr

' IronOCR: native PDF OCR with per-page structured access — no upload
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

Using input As New OcrInput()
    input.LoadPdf("multi-page-invoice.pdf") ' reads locally — no HTTP

    Dim ocr As New IronTesseract()
    Dim result = ocr.Read(input)

    ' Per-page access — not available from Klippa's combined response
    For Each page In result.Pages
        Console.WriteLine($"Page {page.PageNumber}: {page.Lines.Count()} lines")
        Console.WriteLine(page.Text)
    Next

    ' Or produce a searchable PDF from the scanned original
    result.SaveAsSearchablePdf("searchable-output.pdf")
End Using
$vbLabelText   $csharpLabel

IronOCR liest PDF-Dateien nativ, ohne Konvertierungsschritt. Jede Seite ist einzeln mit ihrer vollständigen Zeilen-, Wort- und Zeichenhierarchie zugänglich. Der SaveAsSearchablePdf() Aufruf erzeugt ein Textschicht-PDF aus einem gescannten Dokument — eine Fähigkeit, die Klippa nicht bietet. Der Leitfaden zur PDF-Eingabe beschreibt die Ladeoptionen, und der Leitfaden zur durchsuchbaren PDF-Datei beschreibt die Ausgabeoptionen, einschließlich PDF/A für die Archivierungskonformität.

Klippa OCRAPI zu IronOCR Mapping-Referenz

Klippa ist eine REST-API, kein typisiertes SDK. Die untenstehende Abbildung übersetzt Klippas Integrationsfläche in IronOCR Äquivalente.

Klippa-Konzept IronOCR-Äquivalent
HttpClient mit X-Auth-Key Header IronTesseract Instanz — keine Authentifizierungseinrichtung
MultipartFormDataContent OcrInput.LoadImage(path) oder OcrInput.LoadPdf(path)
POST /api/v1/parseDocument IronTesseract.Read(input)
await _client.PostAsync(...) ocr.Read(input) — synchron, kein await erforderlich
response.EnsureSuccessStatusCode() Nicht erforderlich – keine HTTP-Antwort
JsonSerializer.Deserialize<KlippaResponse>(json) Getyptes OcrResult — keine Deserialisierung
KlippaResponse.Data.ParsedDocument.Text OcrResult.Text
KlippaResponse.Data.ParsedDocument.Amount Benutzerdefinierte Regex auf OcrResult.Text oder OcrResult.Lines
KlippaResponse.Data.ParsedDocument.Merchant OcrResult.Pages[0].Lines[0].Text
Wiederholungsschleife mit Task.Delay Nicht erforderlich – kein Netzwerkausfallmodus
CancellationTokenSource(TimeSpan.FromSeconds(30)) Nicht erforderlich – lokale Ausführung
Ratenbegrenzungsbehandlung (HTTP 429) Nicht erforderlich – keine Ratenbegrenzungen
Cloud-Dokumentenweiterleitung an EU-Server Lokale In-Process-Ausführung
KlippaService.Dispose() / HttpClient.Dispose() OcrInput Entsorgung über using Anweisung
Strukturierte JSON-Antwortfelder OcrResult.Text + OcrResult.Pages + OcrResult.Words
SaaS-API-Abonnement IronOcr.License.LicenseKey string — unbefristet

Gängige Migrationsprobleme und Lösungen

Problem 1: Websites, die nur asynchrone Aufrufe zulassen, nach der Entfernung von HTTP

Klippa: Die gesamte Klippa-Integration ist asynchron, da HTTP-Aufrufe dies erfordern. Controller, Dienste und Hintergrundarbeiter in Ihrem gesamten Codefeld rufen await ProcessDocumentAsync(...) auf. Das Entfernen des HTTP-Aufrufs bedeutet, dass await nicht mehr erforderlich ist, aber die async-Methodensignaturen bleiben.

Lösung:IronOCR bietet sowohl synchrone als auch asynchrone APIs. Für Call-Sites, die asynchron bleiben müssen (ASP.NET Core-Controller, Hintergrunddienste mit CancellationToken), verwenden Sie ReadAsync:

// Keep async method signatures — switch the implementation
public async Task<string> ProcessDocumentAsync(
    string filePath, CancellationToken cancellationToken = default)
{
    // Previously: await _httpClient.PostAsync(...)
    // Now: local call, same awaitable pattern
    var ocr = new IronTesseract();
    var result = await ocr.ReadAsync(filePath);
    return result.Text;
}
// Keep async method signatures — switch the implementation
public async Task<string> ProcessDocumentAsync(
    string filePath, CancellationToken cancellationToken = default)
{
    // Previously: await _httpClient.PostAsync(...)
    // Now: local call, same awaitable pattern
    var ocr = new IronTesseract();
    var result = await ocr.ReadAsync(filePath);
    return result.Text;
}
Imports System.Threading
Imports System.Threading.Tasks

Public Class DocumentProcessor
    Public Async Function ProcessDocumentAsync(filePath As String, Optional cancellationToken As CancellationToken = Nothing) As Task(Of String)
        Dim ocr As New IronTesseract()
        Dim result = Await ocr.ReadAsync(filePath)
        Return result.Text
    End Function
End Class
$vbLabelText   $csharpLabel

Der asynchrone OCR-Leitfaden behandelt ReadAsync und CancellationToken Integration für ASP.NET Core und gehostete Dienstmuster.

Ausgabe 2: Registrierung für Dependency Injection

Klippa: Die KlippaService-Klasse ist in DI als Singleton oder Scoped-Service registriert und umwickelt HttpClient. Die Entfernung erfordert die Aktualisierung der DI-Registrierung und aller Einspeisepunkte.

Lösung: Registrieren Sie IronTesseract als Singleton (es ist thread-sicher) und injizieren Sie es direkt oder erstellen Sie einen dünnen Wrapper, der Ihre bestehende Dienstschnittstelle wiederspiegelt:

// In Program.cs or Startup.cs
builder.Services.AddSingleton<IronTesseract>();

// Or wrap for interface compatibility
builder.Services.AddSingleton<IOcrService, IronOcrService>();

public class IronOcrService : IOcrService
{
    private readonly IronTesseract _ocr;
    public IronOcrService(IronTesseract ocr) => _ocr = ocr;

    public string ReadDocument(string path) => _ocr.Read(path).Text;
}
// In Program.cs or Startup.cs
builder.Services.AddSingleton<IronTesseract>();

// Or wrap for interface compatibility
builder.Services.AddSingleton<IOcrService, IronOcrService>();

public class IronOcrService : IOcrService
{
    private readonly IronTesseract _ocr;
    public IronOcrService(IronTesseract ocr) => _ocr = ocr;

    public string ReadDocument(string path) => _ocr.Read(path).Text;
}
Imports Microsoft.Extensions.DependencyInjection

' In Program.vb or Startup.vb
builder.Services.AddSingleton(Of IronTesseract)()

' Or wrap for interface compatibility
builder.Services.AddSingleton(Of IOcrService, IronOcrService)()

Public Class IronOcrService
    Implements IOcrService

    Private ReadOnly _ocr As IronTesseract

    Public Sub New(ocr As IronTesseract)
        _ocr = ocr
    End Sub

    Public Function ReadDocument(path As String) As String Implements IOcrService.ReadDocument
        Return _ocr.Read(path).Text
    End Function
End Class
$vbLabelText   $csharpLabel

Eine IronTesseract Instanz, die als Singleton registriert ist, bearbeitet gleichzeitige Anfragen. Jeder Aufruf von Read() ist thread-sicher.

Problem 3: Extraktion strukturierter Felder ohne vorab geparstes JSON

Klippa: Klippa liefert amount, merchant, date und vat_amount als typisierte JSON-Eigenschaften zurück. Die Migration zu IronOCR bedeutet, dass diese Felder nicht mehr vorab analysiert werden.

Lösung: IronOCRs OcrResult bietet den Rohtext und die Wortkoordinaten, um eine gleichwertige Extraktion aufzubauen. Bei Dokumenten mit vorhersehbarem Layout zielt die regionenbasierte OCR direkt auf bestimmte Felder ab:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Target specific layout regions instead of relying on pre-parsed cloud fields
var totalRegion   = new CropRectangle(350, 580, 250, 50); // bottom-right total area
var merchantRegion = new CropRectangle(50, 30, 400, 60);  // top header area

using var merchantInput = new OcrInput();
merchantInput.LoadImage("receipt.jpg", merchantRegion);
var merchantName = new IronTesseract().Read(merchantInput).Text.Trim();

using var totalInput = new OcrInput();
totalInput.LoadImage("receipt.jpg", totalRegion);
var totalText = new IronTesseract().Read(totalInput).Text.Trim();
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Target specific layout regions instead of relying on pre-parsed cloud fields
var totalRegion   = new CropRectangle(350, 580, 250, 50); // bottom-right total area
var merchantRegion = new CropRectangle(50, 30, 400, 60);  // top header area

using var merchantInput = new OcrInput();
merchantInput.LoadImage("receipt.jpg", merchantRegion);
var merchantName = new IronTesseract().Read(merchantInput).Text.Trim();

using var totalInput = new OcrInput();
totalInput.LoadImage("receipt.jpg", totalRegion);
var totalText = new IronTesseract().Read(totalInput).Text.Trim();
Imports IronOcr

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

' Target specific layout regions instead of relying on pre-parsed cloud fields
Dim totalRegion As New CropRectangle(350, 580, 250, 50) ' bottom-right total area
Dim merchantRegion As New CropRectangle(50, 30, 400, 60) ' top header area

Using merchantInput As New OcrInput()
    merchantInput.LoadImage("receipt.jpg", merchantRegion)
    Dim merchantName As String = New IronTesseract().Read(merchantInput).Text.Trim()
End Using

Using totalInput As New OcrInput()
    totalInput.LoadImage("receipt.jpg", totalRegion)
    Dim totalText As String = New IronTesseract().Read(totalInput).Text.Trim()
End Using
$vbLabelText   $csharpLabel

Der regionsbasierte OCR-Leitfaden behandelt die CropRectangle Nutzung im Detail. Für vollständige Extraktionsmuster in Beleg- und Rechnungslayouts bietet das Tutorial zum Scannen von Belegen einen kompletten, lauffähigen Code.

Ausgabe 4: Dokumente, die als Datenströme von vorgelagerten Diensten eintreffen

Klippa: Klippa empfängt Dokumente als Multipart-Formular-Uploads – Dateibytes, die in HTTP-Formularinhalte eingebettet sind. Wenn Ihre Anwendung Dokumente als Streams von S3, Azure Blob Storage oder internen APIs empfängt, lesen Sie den Stream in Bytes ein und laden diese Bytes dann zu Klippa hoch.

Lösung:IronOCR akzeptiert Stream Objekte direkt. Der Byte-Konvertierungsschritt entfällt:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Stream from S3, Azure Blob, or any upstream source
public async Task<string> ProcessDocumentStreamAsync(Stream documentStream)
{
    using var input = new OcrInput();
    input.LoadImage(documentStream); // accepts Stream directly

    var ocr = new IronTesseract();
    var result = ocr.Read(input);
    return result.Text;
}
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Stream from S3, Azure Blob, or any upstream source
public async Task<string> ProcessDocumentStreamAsync(Stream documentStream)
{
    using var input = new OcrInput();
    input.LoadImage(documentStream); // accepts Stream directly

    var ocr = new IronTesseract();
    var result = ocr.Read(input);
    return result.Text;
}
Imports System.IO
Imports System.Threading.Tasks
Imports IronOcr

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

Public Async Function ProcessDocumentStreamAsync(documentStream As Stream) As Task(Of String)
    Using input As New OcrInput()
        input.LoadImage(documentStream) ' accepts Stream directly

        Dim ocr As New IronTesseract()
        Dim result = ocr.Read(input)
        Return result.Text
    End Using
End Function
$vbLabelText   $csharpLabel

Kein ReadAllBytes, keine MultipartFormDataContent Konstruktion, kein HTTP-POST. Der Stream geht direkt in OcrInput. Der Leitfaden zur Einleitung von Fließgewässern behandelt Fließgewässertypen und Entsorgungsmuster.

Problem 5: Integrationstests, die auf HTTP-Mocking basieren

Klippa: Integrationstests für Klippa-Code simulieren HttpClient oder verwenden HTTP-Interceptor (z.B. WireMock, MockHttp), um API-Antworten zu simulieren. Diese Tests simulieren die HTTP-Schicht, nicht die OCR-Logik.

Lösung:IronOCR-Tests verwenden reale Dokumente mit bekanntem erwartetem Ergebnis. Keine Infrastruktur zum Verspotten erforderlich. Tests werden offline ausgeführt:

[Fact]
public void ReadDocument_ReturnsExpectedText()
{
    IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
    var ocr = new IronTesseract();

    // Use a real test fixture — no HTTP mocking, runs fully offline
    var result = ocr.Read("test-fixtures/sample-invoice.jpg");

    Assert.Contains("Invoice", result.Text, StringComparison.OrdinalIgnoreCase);
    Assert.True(result.Confidence > 70);
}
[Fact]
public void ReadDocument_ReturnsExpectedText()
{
    IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
    var ocr = new IronTesseract();

    // Use a real test fixture — no HTTP mocking, runs fully offline
    var result = ocr.Read("test-fixtures/sample-invoice.jpg");

    Assert.Contains("Invoice", result.Text, StringComparison.OrdinalIgnoreCase);
    Assert.True(result.Confidence > 70);
}
<Fact>
Public Sub ReadDocument_ReturnsExpectedText()
    IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
    Dim ocr = New IronTesseract()

    ' Use a real test fixture — no HTTP mocking, runs fully offline
    Dim result = ocr.Read("test-fixtures/sample-invoice.jpg")

    Assert.Contains("Invoice", result.Text, StringComparison.OrdinalIgnoreCase)
    Assert.True(result.Confidence > 70)
End Sub
$vbLabelText   $csharpLabel

Tests, die zuvor eine Live-Verbindung zu Klippa oder ein komplexes HTTP-Mock-Setup erforderten, können jetzt in CI ohne Netzwerkzugriff ausgeführt werden.

Problem 6: Minderwertige Dokumente, die Klippa serverseitig verbessert hat

Klippa: Bei der Cloud-Verarbeitung wird die Bildverbesserung vor der Erkennung angewendet. Die Entwickler konfigurieren dies nie – es geschieht automatisch auf den Servern von Klippa. Bei der Migration kann es vorkommen, dass Dokumente, die Klippa im Hintergrund verarbeitet hat, ohne explizite Vorverarbeitung in IronOCR eine geringere Genauigkeit aufweisen.

Lösung: Wenden Sie die Vorverarbeitungsfilter von IronOCR explizit an. Die Filtersätze spiegeln die serverseitigen Einstellungen der Cloud-Dienste wider:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew();    // fix rotation from camera or scanner
input.DeNoise();   // remove compression noise
input.Contrast();  // boost faded ink
input.Binarize();  // clean background for clearer character edges

var result = new IronTesseract().Read(input);
Console.WriteLine($"Confidence: {result.Confidence}%");
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew();    // fix rotation from camera or scanner
input.DeNoise();   // remove compression noise
input.Contrast();  // boost faded ink
input.Binarize();  // clean background for clearer character edges

var result = new IronTesseract().Read(input);
Console.WriteLine($"Confidence: {result.Confidence}%");
Imports IronOcr

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

Using input As New OcrInput()
    input.LoadImage("low-quality-scan.jpg")
    input.Deskew()    ' fix rotation from camera or scanner
    input.DeNoise()   ' remove compression noise
    input.Contrast()  ' boost faded ink
    input.Binarize()  ' clean background for clearer character edges

    Dim result = New IronTesseract().Read(input)
    Console.WriteLine($"Confidence: {result.Confidence}%")
End Using
$vbLabelText   $csharpLabel

Der Leitfaden zur Bildqualitätskorrektur umfasst alle Vorverarbeitungsfilter und die Reihenfolge, in der sie für verschiedene Arten der Dokumentenbeeinträchtigung angewendet werden müssen.

Klippa OCR-Migrationscheckliste

Vor der Migration

Prüfen Sie Ihren Quellcode, um den gesamten Klippa-spezifischen Code zu finden, bevor Sie etwas entfernen:

# Find all files containing Klippa HTTP integration code
grep -r "X-Auth-Key" --include="*.cs" .
grep -r "klippa.com" --include="*.cs" .
grep -r "KlippaService\|KlippaResponse\|KlippaResult\|KlippaData" --include="*.cs" .

# Find all files with MultipartFormDataContent (likely Klippa upload code)
grep -r "MultipartFormDataContent" --include="*.cs" .

# Find all JSON deserialization models that map to Klippa response fields
grep -r "parsed_document\|vat_amount\|merchant\|X-Auth-Key" --include="*.cs" .

# Find all async methods that wrap Klippa calls
grep -r "ParseDocumentAsync\|ProcessReceiptAsync\|UploadAndParseAsync" --include="*.cs" .

# Find test files with HTTP mocks for Klippa
grep -r "MockHttp\|WireMock\|klippa" --include="*.cs" .
# Find all files containing Klippa HTTP integration code
grep -r "X-Auth-Key" --include="*.cs" .
grep -r "klippa.com" --include="*.cs" .
grep -r "KlippaService\|KlippaResponse\|KlippaResult\|KlippaData" --include="*.cs" .

# Find all files with MultipartFormDataContent (likely Klippa upload code)
grep -r "MultipartFormDataContent" --include="*.cs" .

# Find all JSON deserialization models that map to Klippa response fields
grep -r "parsed_document\|vat_amount\|merchant\|X-Auth-Key" --include="*.cs" .

# Find all async methods that wrap Klippa calls
grep -r "ParseDocumentAsync\|ProcessReceiptAsync\|UploadAndParseAsync" --include="*.cs" .

# Find test files with HTTP mocks for Klippa
grep -r "MockHttp\|WireMock\|klippa" --include="*.cs" .
SHELL

Inventarnotizen:

  • Zeichnen Sie jede Klasse auf, die HttpClient für Klippa-Aufrufe umwickelt
  • Listen Sie alle JSON-Deserialisierungsmodellklassen auf (KlippaResponse, KlippaParsedDocument, etc.)
  • Dokumentieren Sie alle Feldzuordnungen, die die vorab geparsten JSON-Eigenschaften von Klippa verwenden.
  • Beachten Sie alle Polly-Wiederholungsrichtlinien oder benutzerdefinierten Wiederholungsschleifen, die für Klippa erstellt wurden

Code-Migration

  1. Installieren Sie IronOcr NuGet-Paket (dotnet add package IronOcr)
  2. Fügen Sie IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY" zum Anwendungsstart hinzu
  3. Entfernen Sie System.Net.Http, System.Text.Json, Newtonsoft.Json Importe aus Klippa-Dienstdateien
  4. Löschen Sie die KlippaService Klasse (oder ersetzen Sie ihren Körper durch IronTesseract Aufrufe und behalten Sie die Schnittstelle bei)
  5. Registrieren Sie IronTesseract als Singleton im DI-Container
  6. Ersetzen Sie MultipartFormDataContent Upload-Blöcke mit OcrInput.LoadImage() oder OcrInput.LoadPdf()
  7. Löschen Sie JSON-Antwortmodellklassen (KlippaResponse, KlippaData, KlippaParsedDocument)
  8. Ersetzen Sie nullable JSON-Navigationsketten (.Data?.ParsedDocument?.Text) mit result.Text
  9. Entfernen Sie Wiederholungsschleifen und CancellationTokenSource Timeouts von Klippa-Aufrufstellen
  10. Ratenbegrenzungsbehandlung entfernen (HTTP 429 Catch-Blöcke)
  11. Ersetzen Sie await ProcessDocumentAsync(...) mit await ocr.ReadAsync(...) oder synchronem ocr.Read(...)
  12. Fügen Sie OcrInput Vorverarbeitungsfilter (Deskew, DeNoise, Contrast) für minderwertige Dokumenteingaben hinzu
  13. Ersetzen Sie die HTTP-Mock-Testinfrastruktur durch reale Dokument-Fixture-Tests.
  14. Polly-Wiederholungsrichtlinien oder benutzerdefinierte Wiederholungs-Middleware, die auf Klippa-Aufrufe beschränkt ist, löschen.

Nach der Migration

  • Überprüfen Sie, ob die Ausgabe der Textextraktion mit dem erwarteten Inhalt bekannter Testdokumente übereinstimmt.
  • Bestätigen, dass die Konfidenzwerte den akzeptablen Schwellenwert (typischerweise 70 %+) für Produktionsdokumenttypen überschreiten.
  • Testen Sie PDF-Eingaben: laden Sie mehrseitige PDFs nativ und verifizieren Sie den seitenweisen Textzugang über result.Pages
  • Testen Sie Stream-Eingaben: führen Sie MemoryStream aus und verifizieren Sie, dass OcrInput.LoadImage(stream) die korrekte Ausgabe erzeugt
  • Überprüfen Sie, ob die Vorverarbeitungsfilter die Genauigkeit bei Scans mit geringer Qualität im Vergleich zur unbearbeiteten Basislinie verbessern.
  • Bestätigen Sie, dass der DI-injizierte IronTesseract Singleton gleichzeitige Anfragen ohne Streitigkeiten bearbeitet
  • Integrationstests offline ausführen (ohne Netzwerkverbindung) – alle Tests sollten ohne Cloud-Zugriff erfolgreich sein.
  • Überprüfen Sie die durchsuchbare PDF-Ausgabe mit result.SaveAsSearchablePdf("output.pdf") für gescannte Dokumentabläufe
  • Testen Sie ReadAsync im ASP.NET Core Controller-Kontext mit CancellationToken-Übertragung
  • Bestätigen Sie, dass das using var input = new OcrInput() Entsorgungsmuster unter andauernder Last keinen Speicher austreten lässt

Wichtigste Vorteile der Migration zu IronOCR

Datensouveränität vom ersten Tag an. Nach der Migration verlassen sensible Finanzdokumente, Identitätsprüfungen und vertrauliche Rechnungen niemals Ihre Infrastruktur. Im Rahmen der Prüfung gibt es keinen externen Datenverarbeiter, keine zu überprüfende Datenaufbewahrungsrichtlinie und keine zu pflegende Datenübertragungsvereinbarung. Die HIPAA-, ITAR-, CMMC- und FedRAMP-Bestimmungen, die Klippa zuvor problematisch gemacht haben, werden standardmäßig erfüllt. Die Bereitstellung auf Docker , AWS oder Azure hält alles innerhalb der Grenzen Ihrer eigenen Infrastruktur.

Infrastrukturkomplexität beseitigt. Die Serviceklasse, der HTTP-Client, der Formular-Upload-Code, die JSON-Modelle, die Wiederholungsrichtlinie, die Timeout-Konfiguration – all das diente dazu, einen Netzwerkaufruf zu kapseln. Entfernt man den Netzwerkaufruf, verschwindet auch alles andere. Die resultierende Codebasis ist kleiner, leichter lesbar und weist weniger Fehlerquellen auf. Eine einzelne IronTesseract Instanz, die über DI injiziert wird, ersetzt die gesamte HTTP-Integrationsschicht.

Vorhersehbare Kosten unabhängig vom Volumen. Eine unbefristete IronOCR-Lizenz für $999 (Lite), 1.499 USD (Professional) oder 2.999 USD (Enterprise) deckt die unbegrenzte Dokumentverarbeitung ab. Die Bearbeitung von 500 Dokumenten pro Monat oder von 500.000 Dokumenten pro Monat kostet gleich viel. Die Abrechnungsdynamik pro Dokument, die Klippa in großem Umfang teuer gemacht hat, fehlt strukturell. Auf der IronOCR -Lizenzseite werden alle Stufen und deren jeweilige Leistungen detailliert aufgeführt.

Grenzenloser Dokumentenumfang.IronOCR verarbeitet jedes Dokument, das Text enthält. Gescannten Verträge, technische Zeichnungen, medizinische Formulare, Bestellungen, handgeschriebene Notizen, Screenshots, TIFF-Archive — alle vom selben Read() Aufruf mit derselben API gehandhabt. Die Beschränkung auf einen speziellen Anwendungsbereich, die ein zweites System für Dokumente außerhalb der von Klippa geschulten Kategorien erforderlich machte, ist aufgehoben. Eine Bibliothek, ein Integrationspunkt, jeder Dokumenttyp.

Offline- und eingeschränkte Netzwerkumgebungen werden jetzt unterstützt. Anwendungen, die in Banknetzwerken, Regierungssystemen, Edge-Umgebungen oder beliebigen Infrastrukturen mit eingeschränktem ausgehendem Datenverkehr eingesetzt werden, funktionieren genauso wie in offenen Umgebungen. Es gibt keine Verbindungsprüfung, keinen Health-Ping an einen Cloud-Endpunkt und keinen eingeschränkten Modus, wenn das Internet nicht verfügbar ist. Air-Gap-Installationen funktionieren ohne Modifikation. Der Linux-Bereitstellungsleitfaden und der Docker-Bereitstellungsleitfaden beschreiben die containerisierten und serverseitigen Bereitstellungswege für diese Umgebungen.

Volle Kontrolle über die Bildverbesserung. Die Cloud-Vorverarbeitung war eine Blackbox – Klippa wandte sie an, man beobachtete die Ergebnisse, ohne Parameter zur Feinabstimmung. IronOCRs Vorverarbeitungspipeline ist explizit und zusammensetzbar: Deskew(), DeNoise(), Contrast(), Binarize(), Sharpen(), Scale(), Dilate(), DeepCleanBackgroundNoise(). Jeder Filter ist optional und wird in einer bestimmten Reihenfolge bestellt. Die Genauigkeitsverbesserungen sind messbar, reproduzierbar und von Ihnen kontrollierbar. Die Seite mit dem Leitfaden zur Bildqualitätskorrektur und den Vorverarbeitungsfunktionen umfasst den gesamten Filterkatalog und gibt Hinweise, wann welcher Filter anzuwenden ist.

Hinweis:Klippa und Tesseract sind eingetragene Marken ihrer jeweiligen Eigentümer. Diese Seite ist nicht mit Google oder Klippa verbunden, unterstützt oder von diesen gesponsert. Alle Produktnamen, Logos und Marken sind Eigentum ihrer jeweiligen Eigentümer. Vergleiche dienen nur zu Informationszwecken und spiegeln öffentlich zugängliche Informationen zum Zeitpunkt des Schreibens wider.

Häufig gestellte Fragen

Warum sollte ich von Klippa OCR API zu IronOCR migrieren?

Zu den häufigsten Gründen gehören die Beseitigung der Komplexität der COM-Interoperabilität, die Ablösung der dateibasierten Lizenzverwaltung, die Vermeidung der seitenweisen Abrechnung, die Ermöglichung der Docker-/Container-Bereitstellung und die Einführung eines NuGet-nativen Workflows, der sich in die Standard-.NET-Werkzeuge integriert.

Was sind die wichtigsten Code-Änderungen bei der Migration von Klippa OCR API zu IronOCR?

Ersetzen Sie Klippa-Initialisierungssequenzen durch IronTesseract-Instanziierung, entfernen Sie das COM-Lebenszyklusmanagement (explizite Create/Load/Close-Muster) und aktualisieren Sie die Namen der Ergebniseigenschaften. Das Ergebnis sind deutlich weniger Boilerplate-Zeilen.

Wie installiere ich IronOCR, um die Migration zu beginnen?

Führen Sie 'Install-Package IronOcr' in der Paketmanager-Konsole oder 'dotnet add package IronOcr' in der CLI aus. Sprachpakete sind separate Pakete: 'dotnet add package IronOcr.Languages.French' für Französisch, zum Beispiel.

Erreicht IronOCR die OCR-Genauigkeit von Klippa OCR API für Standardgeschäftsdokumente?

IronOCR erzielt eine hohe Genauigkeit bei Standardgeschäftsinhalten wie Rechnungen, Verträgen, Quittungen und getippten Formularen. Bildvorverarbeitungsfilter (Schräglagenkorrektur, Rauschunterdrückung, Kontrastverbesserung) verbessern die Erkennungsgenauigkeit bei verschlechterten Eingaben weiter.

Wie geht IronOCR mit den Sprachdaten um, die die Klippa OCR API separat installiert?

Die Sprachdaten in IronOCR werden als NuGet-Pakete verteilt. mit 'dotnet add package IronOcr.Languages.German' wird die deutsche Unterstützung installiert. Es sind keine manuellen Dateiplatzierungen oder Verzeichnispfade erforderlich.

Erfordert die Migration von Klippa OCR API zu IronOCR Änderungen an der Bereitstellungsinfrastruktur?

IronOCR erfordert weniger Änderungen an der Infrastruktur als Klippa OCR API. Es gibt keine SDK-Binärpfade, keine Platzierung von Lizenzdateien oder Lizenzserverkonfigurationen. Das NuGet-Paket enthält die komplette OCR-Engine, und der Lizenzschlüssel ist eine im Anwendungscode festgelegte Zeichenfolge.

Wie konfiguriere ich die IronOCR-Lizenzierung nach der Migration?

Weisen Sie IronOcr.License.LicenseKey = "YOUR-KEY" im Startup-Code der Anwendung zu. In Docker oder Kubernetes speichern Sie den Schlüssel als Umgebungsvariable und lesen ihn beim Starten aus. Verwenden Sie License.IsValidLicense zur Validierung, bevor Sie den Datenverkehr akzeptieren.

Kann IronOCR PDFs auf die gleiche Weise verarbeiten wie Klippa?

Ja, IronOCR liest sowohl native als auch gescannte PDFs. Instanziieren Sie IronTesseract, rufen Sie ocr.Read(input) auf, wobei input ein PDF-Pfad oder OcrPdfInput ist, und iterieren Sie die OcrResult-Seiten. Es ist keine separate PDF-Rendering-Pipeline erforderlich.

Wie handhabt IronOCR das Threading bei der Verarbeitung großer Datenmengen?

IronTesseract kann sicher pro Thread instanziiert werden. Sie können eine Instanz pro Thread in einem Parallel.ForEach- oder Task-Pool aufsetzen, OCR gleichzeitig ausführen und jede Instanz nach Abschluss entsorgen. Es ist kein globaler Zustand oder Sperren erforderlich.

Welche Ausgabeformate unterstützt IronOCR nach der Textextraktion?

IronOCR liefert strukturierte Ergebnisse mit Text, Wortkoordinaten, Konfidenzwerten und Seitenstruktur. Zu den Exportoptionen gehören reiner Text, durchsuchbare PDF-Dateien und strukturierte Ergebnisobjekte für die nachgeschaltete Verarbeitung.

Ist die Preisgestaltung von IronOCR bei der Skalierung von Arbeitslasten berechenbarer als die von Klippa OCR API?

IronOCR verwendet eine pauschale, unbefristete Lizenzierung ohne Seiten- oder Volumengebühren. Egal, ob Sie 10.000 oder 10 Millionen Seiten verarbeiten, die Lizenzkosten bleiben konstant. Optionen für Volumen- und Teamlizenzen finden Sie auf der IronOCR-Preisseite.

Was passiert mit meinen bestehenden Tests nach der Migration von Klippa OCR API zu IronOCR?

Tests, die extrahierte Textinhalte überprüfen, sollten auch nach der Migration bestehen. Tests, die API-Aufrufmuster oder den Lebenszyklus von COM-Objekten validieren, müssen aktualisiert werden, um das einfachere Initialisierungs- und Ergebnismodell von IronOCR widerzuspiegeln.

Kannaopat Udonpant
Software Ingenieur
Bevor er Software-Ingenieur wurde, absolvierte Kannapat ein PhD in Umweltressourcen an der Hokkaido University in Japan. Während seines Studiums wurde Kannapat auch Mitglied des Vehicle Robotics Laboratory, das Teil der Fakultät für Bioproduktionstechnik ist. Im Jahr 2022 nutzte er seine C#-Kenntnisse, um dem Engineering-Team von Iron Software ...
Weiterlesen

Iron-Support-Team

Wir sind 24 Stunden am Tag, 5 Tage die Woche online.
Chat
E-Mail
Rufen Sie mich an