Przejdź do treści stopki
KORZYSTANIE Z IRONBARCODE

Skaner kodów kreskowych ASP.NET: przesyłanie plików i API REST z IronBarcode

Skanowanie kodów kreskowych w ASP.NET staje się proste dzięki IronBarcode: zainstaluj za pomocą NuGet, wywołaj BarcodeReader.Read() i uzyskaj zdekodowane wartości wraz z danymi dotyczącymi typu, pewności i pozycji w jednym kroku — bez konieczności skomplikówanej konfiguracji.

Skanowanie BarCode jest standardowym wymaganiem w nowoczesnych aplikacjach internetowych, wspierającym zarządzanie zapasami, przetwarzanie dokumentów i procesy weryfikacji biletów. Według GS1 BarCODE'y są wykorzystywane codziennie w ponad 6 miliardach transakcji na całym świecie — liczba ta podkreśla, jak kluczowe znaczenie dla każdego systemu biznesowego ma dokładny odczyt BarCODE'ów. Norma ISO/IEC 15415 określa wskaźniki jakości dla symboli kodów kreskowych 2D, natomiast norma ISO/IEC 15416 dotyczy kodów kreskowych liniowych 1D. IronBarcode obsługuje oba te typy kodów w sposób natywny.

Ten przewodnik pokazuje, jak dodać niezawodne skanowanie kodów kreskowych do aplikacji ASP.NET Core przy użyciu IronBarcode, obejmując instalację, przetwarzanie przesyłania plików, integrację REST API oraz wzorce wdrażania produkcyjnego. Na koniec będziesz mieć działający kod zarówno dla skanera przesyłania plików na stronie Razor, jak i punktu końcowego API JSON, który akceptuje obrazy zakodowane w base64 z dowolnego klienta.

Jak zainstalować IronBarcode w projekcie ASP.NET?

Rozpoczęcie pracy zajmuje tylko kilka minut. Biblioteka obsługuje zarówno aplikacje .NET Core, jak i tradycyjne aplikacje ASP.NET MVC, dzięki czemu można ją dostosować do różnych typów projektów. Wdrożenia Enterprise działają równie dobrze na platformach Azure, AWS Lambda i w kontenerach Docker. Wykorzystujące uczenie maszynowe wykrywanie biblioteki radzi sobie z trudnymi obrazami BarCode poprzez automatyczne stosowanie zaawansowanej korekcji obrazu, co jest szczególnie przydatne podczas przetwarzania zdjęć wykonanych aparatami telefonów komórkowych w zmiennych warunkach oświetleniowych.

Instalacja za pomocą menedżera pakietów NuGet

Otwórz konsolę menedżera pakietów w Visual Studio i uruchom:

Install-Package BarCode
Install-Package BarCode
SHELL

Alternatywnie można użyć interfejsu CLI platformy .NET:

dotnet add package BarCode
dotnet add package BarCode
SHELL

Lub wyszukaj "BarCode" w interfejsie użytkownika menedżera pakietów NuGet programu Visual Studio i kliknij opcję Zainstaluj. Pakiet automatycznie zarządza wszystkimi zależnościami.

W przypadku wdrożeń specyficznych dla danej platformy warto rozważyć użycie pakietów NuGet zoptymalizowanych pod kątem docelowego środowiska. Biblioteka oferuje zarówno pakiety standardowe, jak i BarCode.Slim, dostosowane do różnych scenariuszy wdrożeniowych. Pełny opis instalacji znajduje się w przewodniku instalacji IronBarcode.

Konfiguracja projektu

Po zainstalowaniu dodaj niezbędną instrukcję using do plików C#:

using IronBarCode;
using IronBarCode;
Imports IronBarCode
$vbLabelText   $csharpLabel

Ten import zapewnia dostęp do pełnych możliwości IronBarcode w zakresie odczytu i generowania kodów kreskowych. Biblioteka obsługuje ponad 30 formatów BARCODE, w tym QR Code, Code 128, Code 39, Data Matrix i PDF417. Zapoznaj się z pełną listą obsługiwanych formatów BARCODE, aby sprawdzić zgodność z Twoim zastosowaniem.

W przypadku problemów z instalacją należy zapoznać się z przewodnikiem dotyczącym rozwiązywania problemów z pakietami NuGet lub złożyć zgłoszenie techniczne w celu uzyskania specjalistycznego wsparcia.

Wybór odpowiedniego wzorca architektury

Podczas wdrażania skanowania BarCode w ASP.NET dostępne są dwa główne podejścia architektoniczne. Zrozumienie tych wzorców pomoże Ci wybrać odpowiednie ustawienia czytnika BarCode dla każdego przypadku użycia:

// Server-side processing -- recommended for most ASP.NET scenarios
var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true,
    UseConfidenceThreshold = true,
    ConfidenceThreshold = 0.85
};

var results = BarcodeReader.Read(stream, options);

foreach (var barcode in results)
{
    Console.WriteLine($"Type: {barcode.BarcodeType}, Value: {barcode.Text}");
}
// Server-side processing -- recommended for most ASP.NET scenarios
var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true,
    UseConfidenceThreshold = true,
    ConfidenceThreshold = 0.85
};

var results = BarcodeReader.Read(stream, options);

foreach (var barcode in results)
{
    Console.WriteLine($"Type: {barcode.BarcodeType}, Value: {barcode.Text}");
}
Imports System

' Server-side processing -- recommended for most ASP.NET scenarios
Dim options As New BarcodeReaderOptions With {
    .Speed = ReadingSpeed.Balanced,
    .ExpectMultipleBarcodes = True,
    .UseConfidenceThreshold = True,
    .ConfidenceThreshold = 0.85
}

Dim results = BarcodeReader.Read(stream, options)

For Each barcode In results
    Console.WriteLine($"Type: {barcode.BarcodeType}, Value: {barcode.Text}")
Next
$vbLabelText   $csharpLabel

Podejście po stronie serwera zapewnia maksymalną kontrolę nad przetwarzaniem obrazów i działa spójnie we wszystkich przeglądarkach. Gdy serwer przetwarza każdy obraz, otrzymujesz również przejrzystą ścieżkę audytu: każdy zeskanowany BarCode przechodzi przez warstwę aplikacji, gdzie możesz go zarejestrować, zweryfikować w bazie danych lub uruchomić dalsze procesy. Ten wzorzec szczególnie dobrze sprawdza się w branżach podlegających regulacjom, takich jak opieka zdrowotna, logistyka i produkcja, gdzie każde skanowanie musi być rejestrowane.

W przypadku integracji przechwytywania obrazu z kamery po stronie klienta nowoczesne przeglądarki obsługują interfejs API MediaDevices umożliwiający dostęp do kamery, który można połączyć z przetwarzaniem po stronie serwera w IronBarcode za pośrednictwem interfejsu API REST — co zostanie szczegółowo omówione w dalszej części tego przewodnika. Wybór przetwarzania po stronie serwera upraszcza również model bezpieczeństwa: żadna wrażliwa logika przetwarzania nie jest ujawniana przeglądarce, a cała walidacja odbywa się poza granicami aplikacji.

Skanowanie BarCode po stronie klienta a skanowanie po stronie serwera – kompromisy
Aspect Przechwytywanie po stronie klienta + przetwarzanie na serwerze Czyste przetwarzanie po stronie serwera
Najlepsze dla Skanowanie w czasie rzeczywistym za pomocą kamery Przetwarzanie wsadowe, przesyłanie plików
Obsługa przeglądarek Tylko nowoczesne przeglądarki Wszystkie przeglądarki
Doświadczenie użytkownika Natychmiastowa informacja zwrotna Standardowy proces przesyłania plików
Model bezpieczeństwa Bardziej złożone (CORS, autoryzacja) Proste
Wykorzystanie przepustowości Niższy (przetworzony wstępnie na urządzeniu) Wyższa (przesyłanie surowych obrazów)

Jak wdrożyć skanowanie BarCode przy przesyłaniu plików?

Skanowanie plików przesyłanych to najczęstszy scenariusz wykorzystania BarCODE w aplikacjach internetowych ASP.NET. Ten wzorzec sprawdza się przy przetwarzaniu faktur, etykiet wysyłkowych lub dowolnych dokumentów z osadzonymi BARCODE-ami. Aby zwiększyć przepustowość, warto rozważyć wdrożenie asynchronicznego odczytu BarCode, co pozwoli na obsługę wielu przesyłek jednocześnie.

Tworzenie formularza przesyłania

Utwórz responsywny formularz HTML w widoku ASP.NET:

@* Razor view -- barcode upload form *@
<form method="post" enctype="multipart/form-data" id="barcodeForm">
    <div class="form-group">
        <label for="barcodeFile">Select Barcode Image:</label>
        <input type="file" name="barcodeFile" id="barcodeFile"
               accept="image/*,.pdf" class="form-control"
               capture="environment" />
    </div>
    <button type="submit" class="btn btn-primary" id="scanBtn">
        <span class="spinner-border spinner-border-sm d-none" role="status"></span>
        Scan Barcode
    </button>
</form>
<div id="results">
    @ViewBag.BarcodeResult
</div>
@* Razor view -- barcode upload form *@
<form method="post" enctype="multipart/form-data" id="barcodeForm">
    <div class="form-group">
        <label for="barcodeFile">Select Barcode Image:</label>
        <input type="file" name="barcodeFile" id="barcodeFile"
               accept="image/*,.pdf" class="form-control"
               capture="environment" />
    </div>
    <button type="submit" class="btn btn-primary" id="scanBtn">
        <span class="spinner-border spinner-border-sm d-none" role="status"></span>
        Scan Barcode
    </button>
</form>
<div id="results">
    @ViewBag.BarcodeResult
</div>
@* Razor view -- barcode upload form *@
<form method="post" enctype="multipart/form-data" id="barcodeForm">
    <div class="form-group">
        <label for="barcodeFile">Select Barcode Image:</label>
        <input type="file" name="barcodeFile" id="barcodeFile"
               accept="image/*,.pdf" class="form-control"
               capture="environment" />
    </div>
    <button type="submit" class="btn btn-primary" id="scanBtn">
        <span class="spinner-border spinner-border-sm d-none" role="status"></span>
        Scan Barcode
    </button>
</form>
<div id="results">
    @ViewBag.BarcodeResult
</div>
$vbLabelText   $csharpLabel

Atrybut capture="environment" aktywuje tylny aparat w urządzeniach mobilnych, zapewniając użytkownikom wrażenia podobne do korzystania z natywnego aparatu bez użycia JavaScript.

Wdrażanie bezpiecznego przetwarzania zaplecza

Akcja kontrolera obsługuje walidację plików, przetwarzanie strumienia pamięci oraz formatowanie wyników:

[HttpPost]
[ValidateAntiForgeryToken]
[RequestSizeLimit(10_000_000)] // 10MB limit
public async Task<IActionResult> ScanBarcode(IFormFile barcodeFile)
{
    var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif",
                                    ".tiff", ".bmp", ".pdf" };
    var extension = Path.GetExtension(barcodeFile.FileName).ToLowerInvariant();

    if (!allowedExtensions.Contains(extension))
    {
        ModelState.AddModelError("", "Invalid file type");
        return View();
    }

    if (barcodeFile != null && barcodeFile.Length > 0)
    {
        using var stream = new MemoryStream();
        await barcodeFile.CopyToAsync(stream);
        stream.Position = 0;

        var options = new BarcodeReaderOptions
        {
            Speed = ReadingSpeed.Balanced,
            ExpectMultipleBarcodes = true,
            ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional |
                                BarcodeEncoding.QRCode |
                                BarcodeEncoding.DataMatrix,
            ImageFilters = new ImageFilterCollection
            {
                new SharpenFilter(),
                new ContrastFilter()
            }
        };

        var results = BarcodeReader.Read(stream, options);

        ViewBag.BarcodeResult = results.Any()
            ? string.Join("<br/>", results.Select(r => $"<strong>{r.BarcodeType}:</strong> {r.Text}"))
            : "No barcodes found in the image.";
    }

    return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
[RequestSizeLimit(10_000_000)] // 10MB limit
public async Task<IActionResult> ScanBarcode(IFormFile barcodeFile)
{
    var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif",
                                    ".tiff", ".bmp", ".pdf" };
    var extension = Path.GetExtension(barcodeFile.FileName).ToLowerInvariant();

    if (!allowedExtensions.Contains(extension))
    {
        ModelState.AddModelError("", "Invalid file type");
        return View();
    }

    if (barcodeFile != null && barcodeFile.Length > 0)
    {
        using var stream = new MemoryStream();
        await barcodeFile.CopyToAsync(stream);
        stream.Position = 0;

        var options = new BarcodeReaderOptions
        {
            Speed = ReadingSpeed.Balanced,
            ExpectMultipleBarcodes = true,
            ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional |
                                BarcodeEncoding.QRCode |
                                BarcodeEncoding.DataMatrix,
            ImageFilters = new ImageFilterCollection
            {
                new SharpenFilter(),
                new ContrastFilter()
            }
        };

        var results = BarcodeReader.Read(stream, options);

        ViewBag.BarcodeResult = results.Any()
            ? string.Join("<br/>", results.Select(r => $"<strong>{r.BarcodeType}:</strong> {r.Text}"))
            : "No barcodes found in the image.";
    }

    return View();
}
Imports Microsoft.AspNetCore.Mvc
Imports Microsoft.AspNetCore.Http
Imports System.IO
Imports System.Threading.Tasks
Imports ZXing

<HttpPost>
<ValidateAntiForgeryToken>
<RequestSizeLimit(10_000_000)> ' 10MB limit
Public Async Function ScanBarcode(barcodeFile As IFormFile) As Task(Of IActionResult)
    Dim allowedExtensions As String() = {".jpg", ".jpeg", ".png", ".gif", ".tiff", ".bmp", ".pdf"}
    Dim extension As String = Path.GetExtension(barcodeFile.FileName).ToLowerInvariant()

    If Not allowedExtensions.Contains(extension) Then
        ModelState.AddModelError("", "Invalid file type")
        Return View()
    End If

    If barcodeFile IsNot Nothing AndAlso barcodeFile.Length > 0 Then
        Using stream As New MemoryStream()
            Await barcodeFile.CopyToAsync(stream)
            stream.Position = 0

            Dim options As New BarcodeReaderOptions With {
                .Speed = ReadingSpeed.Balanced,
                .ExpectMultipleBarcodes = True,
                .ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional Or
                                      BarcodeEncoding.QRCode Or
                                      BarcodeEncoding.DataMatrix,
                .ImageFilters = New ImageFilterCollection From {
                    New SharpenFilter(),
                    New ContrastFilter()
                }
            }

            Dim results = BarcodeReader.Read(stream, options)

            ViewBag.BarcodeResult = If(results.Any(),
                String.Join("<br/>", results.Select(Function(r) $"<strong>{r.BarcodeType}:</strong> {r.Text}")),
                "No barcodes found in the image.")
        End Using
    End If

    Return View()
End Function
$vbLabelText   $csharpLabel

Ta implementacja sprawdza typ pliku przed przetworzeniem, odczytuje BARCODES ze strumienia pamięci i zwraca wszystkie wykryte wyniki. IronBarcode przetwarza różne formaty obrazów, w tym wielostronicowe pliki TIFF, GIF i dokumenty PDF, eliminując konieczność stosowania kodu obsługującego konkretne formaty.

Jak wygląda zeskanowany tekst źródłowy i docelowy

Kod kreskowy Code 128 z adresem URL

Powyższy przykład przedstawia standardowy BarCode Code 128 — format powszechnie stosowany w aplikacjach do wysyłki i zarządzania zapasami. Po skanowaniu ekran wyników potwierdza zdekodowaną wartość wraz z metadanymi dotyczącymi pewności:

Interfejs aplikacji internetowej ASP.NET Core wyświetlający wyniki pomyślnego skanowania BarCode wraz z formularzem przesyłania plików, pokazującym zdekodowaną wartość BarCode Code128 oraz metadane dotyczące wskaźnika pewności

IronBarcode zwraca typ kodu kreskowego, zdekodowaną wartość, wynik pewności oraz dane dotyczące położenia dla każdego kodu kreskowego wykrytego na przesłanym obrazie.

Jak zbudować interfejs API REST do skanowania BarCodeów?

Nowoczesne aplikacje ASP.NET często udostępniają funkcje skanowania kodów kreskowych za pośrednictwem interfejsów API REST, umożliwiając integrację z aplikacjami mobilnymi, aplikacjami jednostronicowymi lub usługami stron trzecich. Ten wzorzec obsługuje przechwytywanie obrazu z kamery po stronie klienta z przetwarzaniem po stronie serwera.

Kwestie bezpieczeństwa związane z interfejsami API BarCode

Przed napisaniem kontrolera zaplanuj warstwę bezpieczeństwa. Dane BarCode mogą zawierać dowolną treść, dlatego należy zawsze weryfikować wprowadzane dane. Aby zapewnić pełną ochronę, należy przestrzegać wytycznych dotyczących bezpieczeństwa IronBarcode:

  • Sprawdzanie poprawności danych wejściowych: Oczyszczanie treści BarCode przed ich zapisaniem lub wykonaniem operacji na nich
  • Ograniczanie przepustowości: Użyj wbudowanego oprogramowania pośredniczącego .NET Core do ograniczania przepustowości, aby zapobiec nadużyciom API
  • Uwierzytelnianie: Zabezpiecz punkty końcowe za pomocą tokenów JWT lub kluczy API
  • Wymóg stosowania protokołu HTTPS: Cały ruch API związanego z kodami kreskowymi musi odbywać się za pośrednictwem protokołu TLS
  • Polityka CORS: Ogranicz, które źródła mogą wywoływać Twój punkt końcowy skanowania
  • Zarządzanie kluczami licencyjnymi: Prawidłowe stosowanie kluczy licencyjnych i konfigurowanie ich w pliku web.config dla środowiska produkcyjnego

Tworzenie kontrolera API produkcyjnego

[ApiController]
[Route("api/[controller]")]
public class BarcodeController : ControllerBase
{
    private readonly ILogger<BarcodeController> _logger;
    private readonly IMemoryCache _cache;

    public BarcodeController(ILogger<BarcodeController> logger, IMemoryCache cache)
    {
        _logger = logger;
        _cache = cache;
    }

    [HttpPost("scan")]
    [ProducesResponseType(typeof(BarcodeResponse), 200)]
    [ProducesResponseType(typeof(ErrorResponse), 400)]
    public async Task<IActionResult> ScanBarcode([FromBody] BarcodeRequest request)
    {
        try
        {
            if (string.IsNullOrEmpty(request.ImageBase64))
                return BadRequest(new ErrorResponse { Error = "Image data is required" });

            var cacheKey = $"barcode_{request.ImageBase64.GetHashCode()}";
            if (_cache.TryGetValue(cacheKey, out BarcodeResponse cachedResult))
                return Ok(cachedResult);

            byte[] imageBytes = Convert.FromBase64String(request.ImageBase64);

            if (imageBytes.Length > 10 * 1024 * 1024)
                return BadRequest(new ErrorResponse { Error = "Image size exceeds 10MB limit" });

            var options = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Faster,
                ExpectMultipleBarcodes = request.ExpectMultiple ?? false,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.8
            };

            var results = await Task.Run(() => BarcodeReader.Read(imageBytes, options));

            var response = new BarcodeResponse
            {
                Success = true,
                Barcodes = results.Select(r => new BarcodeData
                {
                    Type = r.BarcodeType.ToString(),
                    Value = r.Text,
                    Confidence = r.Confidence,
                    Position = new BarcodePosition
                    {
                        X = r.Points.Select(p => p.X).Min(),
                        Y = r.Points.Select(p => p.Y).Min(),
                        Width = r.Width,
                        Height = r.Height
                    }
                }).ToList()
            };

            _cache.Set(cacheKey, response, TimeSpan.FromMinutes(5));
            return Ok(response);
        }
        catch (FormatException)
        {
            return BadRequest(new ErrorResponse { Error = "Invalid base64 image data" });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing barcode scan");
            return StatusCode(500, new ErrorResponse { Error = "Internal server error" });
        }
    }
}

public record BarcodeRequest(string ImageBase64, bool? ExpectMultiple);

public record BarcodeResponse
{
    public bool Success { get; init; }
    public List<BarcodeData> Barcodes { get; init; } = new();
}

public record BarcodeData
{
    public string Type { get; init; }
    public string Value { get; init; }
    public double Confidence { get; init; }
    public BarcodePosition Position { get; init; }
}

public record BarcodePosition(int X, int Y, int Width, int Height);

public record ErrorResponse
{
    public bool Success => false;
    public string Error { get; init; }
}
[ApiController]
[Route("api/[controller]")]
public class BarcodeController : ControllerBase
{
    private readonly ILogger<BarcodeController> _logger;
    private readonly IMemoryCache _cache;

    public BarcodeController(ILogger<BarcodeController> logger, IMemoryCache cache)
    {
        _logger = logger;
        _cache = cache;
    }

    [HttpPost("scan")]
    [ProducesResponseType(typeof(BarcodeResponse), 200)]
    [ProducesResponseType(typeof(ErrorResponse), 400)]
    public async Task<IActionResult> ScanBarcode([FromBody] BarcodeRequest request)
    {
        try
        {
            if (string.IsNullOrEmpty(request.ImageBase64))
                return BadRequest(new ErrorResponse { Error = "Image data is required" });

            var cacheKey = $"barcode_{request.ImageBase64.GetHashCode()}";
            if (_cache.TryGetValue(cacheKey, out BarcodeResponse cachedResult))
                return Ok(cachedResult);

            byte[] imageBytes = Convert.FromBase64String(request.ImageBase64);

            if (imageBytes.Length > 10 * 1024 * 1024)
                return BadRequest(new ErrorResponse { Error = "Image size exceeds 10MB limit" });

            var options = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Faster,
                ExpectMultipleBarcodes = request.ExpectMultiple ?? false,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.8
            };

            var results = await Task.Run(() => BarcodeReader.Read(imageBytes, options));

            var response = new BarcodeResponse
            {
                Success = true,
                Barcodes = results.Select(r => new BarcodeData
                {
                    Type = r.BarcodeType.ToString(),
                    Value = r.Text,
                    Confidence = r.Confidence,
                    Position = new BarcodePosition
                    {
                        X = r.Points.Select(p => p.X).Min(),
                        Y = r.Points.Select(p => p.Y).Min(),
                        Width = r.Width,
                        Height = r.Height
                    }
                }).ToList()
            };

            _cache.Set(cacheKey, response, TimeSpan.FromMinutes(5));
            return Ok(response);
        }
        catch (FormatException)
        {
            return BadRequest(new ErrorResponse { Error = "Invalid base64 image data" });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing barcode scan");
            return StatusCode(500, new ErrorResponse { Error = "Internal server error" });
        }
    }
}

public record BarcodeRequest(string ImageBase64, bool? ExpectMultiple);

public record BarcodeResponse
{
    public bool Success { get; init; }
    public List<BarcodeData> Barcodes { get; init; } = new();
}

public record BarcodeData
{
    public string Type { get; init; }
    public string Value { get; init; }
    public double Confidence { get; init; }
    public BarcodePosition Position { get; init; }
}

public record BarcodePosition(int X, int Y, int Width, int Height);

public record ErrorResponse
{
    public bool Success => false;
    public string Error { get; init; }
}
Imports System
Imports Microsoft.AspNetCore.Mvc
Imports Microsoft.Extensions.Logging
Imports Microsoft.Extensions.Caching.Memory
Imports System.Threading.Tasks

<ApiController>
<Route("api/[controller]")>
Public Class BarcodeController
    Inherits ControllerBase

    Private ReadOnly _logger As ILogger(Of BarcodeController)
    Private ReadOnly _cache As IMemoryCache

    Public Sub New(logger As ILogger(Of BarcodeController), cache As IMemoryCache)
        _logger = logger
        _cache = cache
    End Sub

    <HttpPost("scan")>
    <ProducesResponseType(GetType(BarcodeResponse), 200)>
    <ProducesResponseType(GetType(ErrorResponse), 400)>
    Public Async Function ScanBarcode(<FromBody> request As BarcodeRequest) As Task(Of IActionResult)
        Try
            If String.IsNullOrEmpty(request.ImageBase64) Then
                Return BadRequest(New ErrorResponse With {.Error = "Image data is required"})
            End If

            Dim cacheKey = $"barcode_{request.ImageBase64.GetHashCode()}"
            Dim cachedResult As BarcodeResponse = Nothing
            If _cache.TryGetValue(cacheKey, cachedResult) Then
                Return Ok(cachedResult)
            End If

            Dim imageBytes As Byte() = Convert.FromBase64String(request.ImageBase64)

            If imageBytes.Length > 10 * 1024 * 1024 Then
                Return BadRequest(New ErrorResponse With {.Error = "Image size exceeds 10MB limit"})
            End If

            Dim options = New BarcodeReaderOptions With {
                .Speed = ReadingSpeed.Faster,
                .ExpectMultipleBarcodes = request.ExpectMultiple.GetValueOrDefault(False),
                .UseConfidenceThreshold = True,
                .ConfidenceThreshold = 0.8
            }

            Dim results = Await Task.Run(Function() BarcodeReader.Read(imageBytes, options))

            Dim response = New BarcodeResponse With {
                .Success = True,
                .Barcodes = results.Select(Function(r) New BarcodeData With {
                    .Type = r.BarcodeType.ToString(),
                    .Value = r.Text,
                    .Confidence = r.Confidence,
                    .Position = New BarcodePosition With {
                        .X = r.Points.Select(Function(p) p.X).Min(),
                        .Y = r.Points.Select(Function(p) p.Y).Min(),
                        .Width = r.Width,
                        .Height = r.Height
                    }
                }).ToList()
            }

            _cache.Set(cacheKey, response, TimeSpan.FromMinutes(5))
            Return Ok(response)
        Catch ex As FormatException
            Return BadRequest(New ErrorResponse With {.Error = "Invalid base64 image data"})
        Catch ex As Exception
            _logger.LogError(ex, "Error processing barcode scan")
            Return StatusCode(500, New ErrorResponse With {.Error = "Internal server error"})
        End Try
    End Function
End Class

Public Class BarcodeRequest
    Public Property ImageBase64 As String
    Public Property ExpectMultiple As Boolean?
End Class

Public Class BarcodeResponse
    Public Property Success As Boolean
    Public Property Barcodes As List(Of BarcodeData) = New List(Of BarcodeData)()
End Class

Public Class BarcodeData
    Public Property Type As String
    Public Property Value As String
    Public Property Confidence As Double
    Public Property Position As BarcodePosition
End Class

Public Class BarcodePosition
    Public Property X As Integer
    Public Property Y As Integer
    Public Property Width As Integer
    Public Property Height As Integer
End Class

Public Class ErrorResponse
    Public ReadOnly Property Success As Boolean
        Get
            Return False
        End Get
    End Property
    Public Property Error As String
End Class
$vbLabelText   $csharpLabel

Ten punkt końcowy akceptuje obrazy zakodowane w formacie base64 — standardowym formacie przesyłania obrazów przez HTTP. Odpowiedź zawiera typ BARCODE, zdekodowaną wartość, wynik pewności oraz pozycję. W przypadku dużych ilości danych warto zapoznać się z opcjami przetwarzania partii BARCODE-ów oraz optymalizacji szybkości odczytu.

W jaki sposób API obsługuje wiele BarCodes?

Trzy różne formaty BarCODE oznaczone literami A, B i C, przedstawiające symbole QR Code, Code128 i DataMatrix, które IronBarcode przetwarza jednocześnie w środowiskach produkcyjnych

IronBarcode przetwarza wiele kodów kreskowych w jednym obrazie za pomocą jednego wywołania, zwracając tablicę wyników. Każdy wpis w odpowiedzi zawiera dane o położeniu, dzięki czemu aplikacja kliencka może podświetlić wykryte BARCODE na ekranie.

Karta sieciowa narzędzi programistycznych przeglądarki pokazująca pomyślną odpowiedź API JSON zawierającą tablicę trzech wykrytych BarCodes wraz z kompletnymi metadanymi, w tym typem, wartością, poziomem pewności i współrzędnymi pozycji

Strukturalna odpowiedź JSON zapewnia aplikacjom klienckim wszystko, co jest potrzebne do przetwarzania i wyświetlania wyników skanowania BARCODE bez konieczności dodatkowego wyszukiwania.

Jak radzisz sobie z trudnymi obrazami BarCode?

W praktyce skanowanie kodów kreskowych często wiąże się z niedoskonałymi obrazami — zdjęciami wykonanymi pod kątem, przy słabym oświetleniu lub z częściowo uszkodzonymi kodami kreskowymi. IronBarcode radzi sobie z tymi scenariuszami dzięki zaawansowanym możliwościom przetwarzania obrazu i progom pewności opartym na uczeniu maszynowym.

Diagnozowanie typowych problemów związanych ze skanowaniem

Przed wprowadzeniem poprawek określ, do której kategorii należy dany problem. Większość błędów skanowania w środowisku produkcyjnym można podzielić na pięć grup: problemy z jakością obrazu (rozmycie, szumy, niska rozdzielczość), problemy geometryczne (obrót, przekrzywienie, zniekształcenie perspektywy), problemy związane z uszkodzeniami (podarte etykiety, rozmazany tusz), problemy środowiskowe (odblaski, cienie, nierównomierne oświetlenie) oraz fałszywie pozytywne wykrycie, w którym czytnik wykrywa BARCODE, który nie istnieje.

Znajomość kategorii pomaga dobrać odpowiednią kombinację filtrów i prędkość odczytu bez konieczności przeprowadzania zbędnego przetwarzania każdego obrazu. W przypadku większości scenariuszy aplikacji internetowych, rozpoczęcie od ReadingSpeed.Balanced i AutoRotate = true obejmuje większość przypadków. Przekaż sprawę do ExtremeDetail tylko wtedy, gdy pierwsze przejście nie przyniesie żadnych wyników.

Podejście wieloetapowe w poniższym kodzie realizuje tę wielopoziomową strategię. Szybki pierwszy przebieg szybko obsługuje typowe obrazy, utrzymując niskie opóźnienie średnie w typowych przypadkach. Szczegółowa druga faza przetwarzania jest uruchamiana tylko wtedy, gdy pierwsza faza zakończy się niepowodzeniem, co gwarantuje, że ponosisz dodatkowe koszty przetwarzania tylko wtedy, gdy jest to rzeczywiście konieczne. Ten wzorzec zapewnia responsywność punktu końcowego ASP.NET przy normalnym obciążeniu, a jednocześnie niezawodnie obsługuje trudne przypadki skrajne.

Typowe problemy związane ze skanowaniem BarCodes i ich rozwiązania
Problem Objaw Rozwiązanie
Niewyraźny obraz Niskie wyniki pewności, pominięte fragmenty Zastosuj filtr SharpenFilter, zwiększ prędkość ExtremeDetail
Obrócony BarCode BarCode nie został wykryty Włącz AutoRotate = true
Uszkodzony BarCode Częściowe odczyty, nieprawidłowe wartości Włącz korektę błędów, użyj RemoveFalsePositive
Słaby kontrast Wykrywanie niespójności Zastosuj filtry ContrastFilter i BrightnessFilter
Zbyt wolne działanie Duże opóźnienia podczas przesyłania plików Użyj ReadingSpeed.Faster, włącz wielowątkowość

Wdrażanie wieloprzebiegówego przetwarzania obrazów

W przypadku trudnych obrazów najlepsze wyniki daje podejście oparte na przetwarzaniu warstwowym, które nie obniża wydajności w przypadku łatwych obrazów:

public class AdvancedBarcodeProcessor
{
    private readonly ILogger<AdvancedBarcodeProcessor> _logger;

    public async Task<List<ScannedBarcode>> ProcessChallengingImage(Stream imageStream)
    {
        // First pass -- fast, minimal processing
        var fastOptions = new BarcodeReaderOptions
        {
            Speed = ReadingSpeed.Balanced,
            ExpectMultipleBarcodes = true,
            AutoRotate = false,
            UseConfidenceThreshold = true,
            ConfidenceThreshold = 0.85
        };

        var results = BarcodeReader.Read(imageStream, fastOptions);

        if (!results.Any())
        {
            // Second pass -- aggressive image correction
            imageStream.Position = 0;

            var detailedOptions = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.ExtremeDetail,
                ExpectMultipleBarcodes = true,
                AutoRotate = true,
                RemoveFalsePositive = true,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.6,
                Multithreaded = true,
                ExpectBarcodeTypes = BarcodeEncoding.All,
                ImageFilters = new ImageFilterCollection
                {
                    new SharpenFilter(2.5f),
                    new ContrastFilter(2.0f),
                    new BrightnessFilter(1.2f),
                    new InvertFilter()
                }
            };

            results = BarcodeReader.Read(imageStream, detailedOptions);
            _logger.LogInformation("Second pass detected {Count} barcodes", results.Count());
        }

        return results.Select(r => new ScannedBarcode
        {
            Value = r.Text,
            BarcodeType = r.BarcodeType.ToString(),
            Confidence = r.Confidence,
            RotationAngle = r.RotationAngle,
            PageNumber = r.PageNumber
        }).ToList();
    }
}

public record ScannedBarcode
{
    public string Value { get; init; }
    public string BarcodeType { get; init; }
    public double Confidence { get; init; }
    public float RotationAngle { get; init; }
    public int PageNumber { get; init; }
}
public class AdvancedBarcodeProcessor
{
    private readonly ILogger<AdvancedBarcodeProcessor> _logger;

    public async Task<List<ScannedBarcode>> ProcessChallengingImage(Stream imageStream)
    {
        // First pass -- fast, minimal processing
        var fastOptions = new BarcodeReaderOptions
        {
            Speed = ReadingSpeed.Balanced,
            ExpectMultipleBarcodes = true,
            AutoRotate = false,
            UseConfidenceThreshold = true,
            ConfidenceThreshold = 0.85
        };

        var results = BarcodeReader.Read(imageStream, fastOptions);

        if (!results.Any())
        {
            // Second pass -- aggressive image correction
            imageStream.Position = 0;

            var detailedOptions = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.ExtremeDetail,
                ExpectMultipleBarcodes = true,
                AutoRotate = true,
                RemoveFalsePositive = true,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.6,
                Multithreaded = true,
                ExpectBarcodeTypes = BarcodeEncoding.All,
                ImageFilters = new ImageFilterCollection
                {
                    new SharpenFilter(2.5f),
                    new ContrastFilter(2.0f),
                    new BrightnessFilter(1.2f),
                    new InvertFilter()
                }
            };

            results = BarcodeReader.Read(imageStream, detailedOptions);
            _logger.LogInformation("Second pass detected {Count} barcodes", results.Count());
        }

        return results.Select(r => new ScannedBarcode
        {
            Value = r.Text,
            BarcodeType = r.BarcodeType.ToString(),
            Confidence = r.Confidence,
            RotationAngle = r.RotationAngle,
            PageNumber = r.PageNumber
        }).ToList();
    }
}

public record ScannedBarcode
{
    public string Value { get; init; }
    public string BarcodeType { get; init; }
    public double Confidence { get; init; }
    public float RotationAngle { get; init; }
    public int PageNumber { get; init; }
}
Imports System.IO
Imports System.Collections.Generic
Imports System.Linq
Imports System.Threading.Tasks

Public Class AdvancedBarcodeProcessor
    Private ReadOnly _logger As ILogger(Of AdvancedBarcodeProcessor)

    Public Async Function ProcessChallengingImage(imageStream As Stream) As Task(Of List(Of ScannedBarcode))
        ' First pass -- fast, minimal processing
        Dim fastOptions As New BarcodeReaderOptions With {
            .Speed = ReadingSpeed.Balanced,
            .ExpectMultipleBarcodes = True,
            .AutoRotate = False,
            .UseConfidenceThreshold = True,
            .ConfidenceThreshold = 0.85
        }

        Dim results = BarcodeReader.Read(imageStream, fastOptions)

        If Not results.Any() Then
            ' Second pass -- aggressive image correction
            imageStream.Position = 0

            Dim detailedOptions As New BarcodeReaderOptions With {
                .Speed = ReadingSpeed.ExtremeDetail,
                .ExpectMultipleBarcodes = True,
                .AutoRotate = True,
                .RemoveFalsePositive = True,
                .UseConfidenceThreshold = True,
                .ConfidenceThreshold = 0.6,
                .Multithreaded = True,
                .ExpectBarcodeTypes = BarcodeEncoding.All,
                .ImageFilters = New ImageFilterCollection From {
                    New SharpenFilter(2.5F),
                    New ContrastFilter(2.0F),
                    New BrightnessFilter(1.2F),
                    New InvertFilter()
                }
            }

            results = BarcodeReader.Read(imageStream, detailedOptions)
            _logger.LogInformation("Second pass detected {Count} barcodes", results.Count())
        End If

        Return results.Select(Function(r) New ScannedBarcode With {
            .Value = r.Text,
            .BarcodeType = r.BarcodeType.ToString(),
            .Confidence = r.Confidence,
            .RotationAngle = r.RotationAngle,
            .PageNumber = r.PageNumber
        }).ToList()
    End Function
End Class

Public Class ScannedBarcode
    Public Property Value As String
    Public Property BarcodeType As String
    Public Property Confidence As Double
    Public Property RotationAngle As Single
    Public Property PageNumber As Integer
End Class
$vbLabelText   $csharpLabel

Klasa BarcodeReaderOptions zapewnia precyzyjną kontrolę nad każdym aspektem skanowania. Ustawienie AutoRotate obsługuje obrazy przechwycone pod dowolnym kątem, a filtry obrazu poprawiają wyrazistość rozmytych lub mało kontrastowych BARCODE-ów. Szczegółowe informacje na temat konfiguracji można znaleźć w przykładzie ustawień czytnika BarCode oraz w ustawieniach czytnika dotyczących plików PDF.

Podczas pracy z plikami PDF warto rozważyć umieszczenie BARCODE-ów na plikach PDF lub tworzenie BARCODE-ów jako dokumentów PDF. W przypadku przetwarzania dużych ilości danych włączenie wielowątkowości za pomocą funkcji async i multithread znacznie poprawia przepustowość.

Dodanie strategii kompatybilności z przeglądarkami i strategii awaryjnych

Obsługa różnych przeglądarek wymaga stopniowego ulepszania. Nowoczesne przeglądarki na Androida oraz przeglądarki Chrome, Edge i Firefox na komputery stacjonarne obsługują interfejs API MediaDevices.getUserMedia() umożliwiający dostęp do aparatu. Safari na iOS obsługuje tę funkcję od wersji 11. Starsze przeglądarki Enterprise, tryby zgodności IE11 oraz niektóre zablokowane środowiska Enterprise mogą w ogóle nie obsługiwać dostępu do kamery, dlatego rezerwowa ścieżka przesyłania plików musi zawsze pozostawać funkcjonalna.

Zalecanym podejściem jest wykorzystanie wykrywania funkcji w czasie wykonywania zamiast sprawdzania agenta użytkownika, a następnie odpowiednie wyświetlanie lub ukrywanie interfejsu kamery. Zacznij od interfejsu obsługującego kamerę, a w razie potrzeby płynnie przejdź do przesyłania plików:

@* Razor view with progressive enhancement *@
<div class="barcode-scanner-container">
    @* Camera capture -- hidden until JavaScript confirms support *@
    <div id="cameraSection" class="d-none">
        <video id="videoPreview" class="w-100" autoplay></video>
        <button id="captureBtn" class="btn btn-primary mt-2">Capture and Scan</button>
    </div>

    @* File upload -- always available as fallback *@
    <div id="uploadSection">
        <form method="post" enctype="multipart/form-data"
              asp-action="ScanBarcode" asp-controller="Barcode">
            <div class="form-group">
                <label>Upload Barcode Image:</label>
                <input type="file" name="file" accept="image/*,.pdf"
                       class="form-control" required />
            </div>
            <button type="submit" class="btn btn-primary">Upload and Scan</button>
        </form>
    </div>
</div>
@* Razor view with progressive enhancement *@
<div class="barcode-scanner-container">
    @* Camera capture -- hidden until JavaScript confirms support *@
    <div id="cameraSection" class="d-none">
        <video id="videoPreview" class="w-100" autoplay></video>
        <button id="captureBtn" class="btn btn-primary mt-2">Capture and Scan</button>
    </div>

    @* File upload -- always available as fallback *@
    <div id="uploadSection">
        <form method="post" enctype="multipart/form-data"
              asp-action="ScanBarcode" asp-controller="Barcode">
            <div class="form-group">
                <label>Upload Barcode Image:</label>
                <input type="file" name="file" accept="image/*,.pdf"
                       class="form-control" required />
            </div>
            <button type="submit" class="btn btn-primary">Upload and Scan</button>
        </form>
    </div>
</div>
@* Razor view with progressive enhancement *@
<div class="barcode-scanner-container">
    @* Camera capture -- hidden until JavaScript confirms support *@
    <div id="cameraSection" class="d-none">
        <video id="videoPreview" class="w-100" autoplay></video>
        <button id="captureBtn" class="btn btn-primary mt-2">Capture and Scan</button>
    </div>

    @* File upload -- always available as fallback *@
    <div id="uploadSection">
        <form method="post" enctype="multipart/form-data"
              asp-action="ScanBarcode" asp-controller="Barcode">
            <div class="form-group">
                <label>Upload Barcode Image:</label>
                <input type="file" name="file" accept="image/*,.pdf"
                       class="form-control" required />
            </div>
            <button type="submit" class="btn btn-primary">Upload and Scan</button>
        </form>
    </div>
</div>
$vbLabelText   $csharpLabel

Integracja z Blazorem zapewnia obsługę nowoczesnych aplikacji internetowych przy minimalnej konfiguracji, jeśli preferujesz podejście oparte na komponentach. W przypadku rozwiązywania problemów związanych z wdrażaniem należy zapoznać się z przewodnikiem dotyczącym wyjątków kopiowania środowisk uruchomieniowych.

Jakie są Twoje kolejne kroki?

Skanowanie kodów kreskowych w ASP.NET jest proste dzięki IronBarcode. Wystarczy zainstalować jeden pakiet NuGet, wywołać BarcodeReader.Read() i uzyskać wiarygodne wyniki dekodowania w ponad 30 formatach — w tym trudnych, rzeczywistych obrazach, z którymi inne biblioteki mają problemy.

Aby dalej rozwijać się w tym zakresie, zapoznaj się z poniższymi zasobami:

Zacznij od bezpłatnej licencji próbnej, aby przetestować IronBarcode w swojej aplikacji ASP.NET bez żadnych ograniczeń. Wersja próbna zapewnia pełny dostęp do wszystkich funkcji, w tym wykrywania wielu formatów, korekcji obrazów oraz wzorców REST API przedstawionych w tym przewodniku — dzięki czemu można ocenić wydajność na własnych obrazach przed zakupem licencji produkcyjnej. W przypadku aplikacji mobilnych .NET MAUI, które wymagają skanowania na urządzeniu, zapoznaj się z samouczkiem dotyczącym skanera BARCODE .NET MAUI, który rozszerza ten sam interfejs API na platformy iOS i Android.

Często Zadawane Pytania

Jakie jest główne zastosowanie skanowania BarCode w aplikacjach ASP.NET?

Skanowanie BarCode w aplikacjach ASP.NET służy przede wszystkim do usprawnienia systemów zarządzania zapasami, obsługi biletów podczas wydarzeń oraz digitalizacji dokumentów papierowych, co pozwala zwiększyć wydajność i ograniczyć liczbę błędów.

W jaki sposób IronBarcode ułatwia skanowanie kodów kreskowych w ASP.NET?

IronBarcode upraszcza proces skanowania kodów kreskowych w ASP.NET, dostarczając niezawodne i wydajne komponenty, które można łatwo zintegrować z aplikacjami internetowymi, umożliwiając programistom szybkie wdrażanie funkcji skanowania.

Jakie rodzaje kodów kreskowych można skanować za pomocą IronBarcode?

IronBarcode obsługuje skanowanie szerokiej gamy formatów kodów kreskowych, w tym tradycyjnych kodów liniowych i nowoczesnych kodów 2D, zapewniając kompatybilność z różnorodnymi aplikacjami.

Czy IronBarcode może obsługiwać skanowanie kodów kreskowych do przetwarzania dokumentów?

Tak, IronBarcode doskonale nadaje się do procesów przetwarzania dokumentów, gdzie może służyć do digitalizacji i porządkowania dokumentów papierowych poprzez skanowanie wbudowanych kodów kreskowych.

Czy IronBarcode nadaje się do systemów zarządzania zapasami?

IronBarcode to doskonały wybór dla systemów zarządzania zapasami, ponieważ umożliwia wydajne śledzenie produktów poprzez skanowanie kodów kreskowych, usprawniając w ten sposób operacje i minimalizując błędy.

W jaki sposób integracja IronBarcode usprawnia przetwarzanie biletów na wydarzenia?

Dzięki integracji z IronBarcode przetwarzanie biletów na wydarzenia staje się płynne, ponieważ umożliwia szybkie skanowanie kodów kreskowych biletów, ułatwiając szybkie i dokładne zarządzanie wejściami podczas wydarzeń.

Jakie są zalety korzystania z IronBarcode w projektach ASP.NET?

Wykorzystanie IronBarcode w projektach ASP.NET oferuje szereg korzyści, w tym łatwość integracji, obsługę wielu formatów kodów kreskowych oraz zwiększoną wydajność aplikacji, zapewniając w ten sposób solidne rozwiązanie dla potrzeb skanowania kodów kreskowych.

Czy wdrożenie IronBarcode wymaga rozległej wiedzy z zakresu programowania?

Nie, IronBarcode został zaprojektowany z myślą o programistach, co ułatwia wdrażanie funkcji skanowania kodów kreskowych w aplikacjach ASP.NET przy minimalnej wiedzy programistycznej.

Czy IronBarcode może być używany w mobilnych aplikacjach internetowych?

Tak, IronBarcode można zintegrować z mobilnymi aplikacjami internetowymi, co pozwala na skanowanie kodów kreskowych w dowolnym miejscu i zwiększa wszechstronność projektów ASP.NET.

Jordi Bardia
Inżynier oprogramowania
Jordi jest najbardziej biegły w Pythonie, C# i C++. Kiedy nie wykorzystuje swoich umiejętności w Iron Software, programuje gry. Dzieląc odpowiedzialność za testowanie produktów, rozwój produktów i badania, Jordi wnosi ogromną wartość do ciągłej poprawy produktów. Różnorodne doświadczenia ...
Czytaj więcej

Zespol wsparcia Iron

Jestesmy online 24 godziny, 5 dni w tygodniu.
Czat
Email
Zadzwon do mnie