跳過到頁腳內容
使用IRONBARCODE

ASP.NET條碼掃描器:文件上傳和REST API與IronBarcode

使用 IronBarcode,ASP.NET 中的條碼掃描變得非常簡單:透過 NuGet 安裝,呼叫 BarcodeReader.Read(),即可一步取得包含類型、置信度和位置資料的解碼值-無需複雜的配置。

條碼掃描是現代網路應用程式的標準要求,為庫存管理、文件處理和票據驗證工作流程提供支援。 根據GS1統計,全球每天有超過 60 億筆交易使用條碼——這一數字凸顯了準確讀取條碼對於任何商業系統的重要性。 ISO/IEC 15415標準定義了二維條碼符號的品質指標,而ISO/IEC 15416標準涵蓋了一維線性條碼,IronBarcode 對這兩種標準都提供了原生支援。

本指南向您展示如何使用 IronBarcode 為您的 ASP.NET Core 應用程式添加可靠的條碼掃描功能,內容涵蓋安裝、檔案上傳處理、REST API 整合和生產部署模式。 到最後,你將擁有 Razor 頁面檔案上傳掃描器和 JSON API 端點的可用程式碼,該端點可以接受來自任何客戶端的 base64 編碼圖像。

如何在 ASP.NET 專案中安裝 IronBarcode?

入門只需幾分鐘。 該程式庫同時支援 ASP.NET Core 和傳統的 ASP.NET MVC 應用程序,因此能夠適應各種專案類型。企業級部署在AzureAWS LambdaDocker 容器上都能完美運作。 該庫的機器學習偵測功能透過自動應用複雜的影像校正來處理具有挑戰性的條碼影像,這在處理使用行動相機在多變的光照條件下拍攝的照片時特別有用。

透過 NuGet 套件管理器安裝

在 Visual Studio 中開啟套件管理員控制台並執行:

Install-Package BarCode
Install-Package BarCode
SHELL

或者,使用 .NET CLI:

dotnet add package BarCode
dotnet add package BarCode
SHELL

或在 Visual Studio NuGet 套件管理器 UI 中搜尋"BarCode",然後按一下"安裝"。 該軟體包會自動管理所有相依性。

對於特定平台的部署,請考慮使用針對目標環境最佳化的特定平台 NuGet 套件。 該程式庫提供標準版和BarCode.Slim 版,以適應不同的部署場景。 有關完整的安裝步驟,請參閱IronBarcode 安裝指南

配置您的項目

安裝完成後,將必要的 using 語句加入您的 C# 檔案:

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

匯入此軟體後,您將可以使用 IronBarcode 的完整條碼讀取產生功能。 本函式庫支援超過 30 種條碼格式,包括二維碼、Code 128、Code 39、Data Matrix 和 PDF417。查看支援的條碼格式完整列表,以確認其與您的使用場景相容。

如需排查安裝問題,請參閱NuGet 套件故障排除指南或提交工程支援請求以獲得專門支援。

選擇合適的架構模式

在 ASP.NET 中實作條碼掃描時,主要有兩種架構方法。 了解這些規則有助於您針對每種使用情境選擇合適的條碼閱讀器設定

// 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

伺服器端方法可讓您最大限度地控制影像處理,並且在所有瀏覽器上都能穩定運作。 當伺服器處理每個影像時,您還可以獲得清晰的審計追蹤:每個掃描的條碼都會經過您的應用程式層,您可以在其中記錄它、根據資料庫驗證它或觸發下游工作流程。 這種模式尤其適用於醫療保健、物流和製造業等受監管行業,因為在這些行業中,每一次掃描都必須記錄在案。

對於客戶端攝影機擷取集成,現代瀏覽器支援用於存取攝影機的 API,該 API 可以與 IronBarcode 的伺服器端處理功能(透過 REST API 實現)相結合——本指南稍後將詳細介紹。選擇伺服器端處理還可以簡化您的安全模型:無需向瀏覽器暴露任何敏感的處理邏輯,所有驗證都在您的應用程式邊界內進行。

用戶端與伺服器端條碼掃描的優缺點
範疇 客戶端捕獲 + 伺服器處理 純伺服器端處理
最適合 使用攝影機進行即時掃描 批次處理、文件上傳
瀏覽器支援 僅限現代瀏覽器 所有瀏覽器
使用者體驗 即時回饋 標準上傳流程
安全模型 更複雜(CORS、身份驗證) 直截了當
頻寬使用情況 較低(設備上預處理) 更高(原始圖像上傳)

如何實現文件上傳條碼掃描?

檔案上傳掃描是 ASP.NET Web 應用程式中最常見的條碼應用程式場景。 此模式適用於處理發票、貨運標籤或任何具有嵌入式條碼的文件。 為了提高吞吐量,可以考慮採用非同步條碼讀取來同時處理多個上傳任務。

建立上傳表單

在 ASP.NET 視圖中建立響應式 HTML 表單:

@* 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

capture="environment" 屬性可啟動行動裝置上的後置鏡頭,使用戶無需 JavaScript 即可獲得類似原生相機的體驗。

實施安全後端處理

控制器操作負責文件驗證、記憶體流處理和結果格式化:

[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

此實作會在處理之前驗證檔案類型,從記憶體流中讀取條碼,並傳回所有偵測到的結果。 IronBarcode 可處理各種影像格式,包括多頁 TIFF、GIFPDF 文檔,無需編寫特定於格式的處理代碼。

掃描的輸入和輸出是什麼樣子的

Code 128 條碼編碼 URL 'https://ironsoftware.com/csharp/barcode/'; 顯示機器可讀取的條碼,下方帶有人類可讀的文本,以便在 ASP.NET 條碼閱讀器應用程式中進行準確掃描。

上面的範例顯示了一個標準的 Code 128 條碼——這是運輸和庫存應用中常見的格式。 掃描完成後,結果畫面會確認解碼值以及置信度元資料:

! ASP.NET Core Web 應用程式介面顯示條碼掃描成功結果,檔案上傳表單顯示解碼後的 Code128 條碼值和置信度評分元數據

IronBarcode 傳回上傳影像中偵測到的每個條碼的類型、解碼值、置信度分數和位置資料。

如何建立用於條碼掃描的 REST API?

現代 ASP.NET 應用程式通常透過 REST API 公開條碼掃描功能,從而可以與行動應用程式、單頁應用程式或第三方服務整合。 這種模式支援客戶端攝影機擷取和伺服器端處理。

條碼API的安全注意事項

在編寫控制器之前,先規劃安全層。 條碼資料可能包含任意內容,因此請務必驗證輸入。 請遵循IronBarcode 安全指南以獲得全面保護:

-輸入驗證:在儲存或處理條碼內容之前進行清理。 -速率限制:使用 ASP.NET Core 內建的速率限制中間件來防止 API 濫用 -身份驗證:使用 JWT 令牌或 API 金鑰保護端點 -強制執行 HTTPS :所有條碼 API 流量必須透過 TLS 傳輸。

建構生產 API 控制器

[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

此介面接受 base64 編碼的映像-這是透過 HTTP 傳輸影像的標準格式。回應包含條碼類型、解碼值、置信度評分和位置。 對於大批量處理場景,請查看批次條碼處理讀取速度最佳化選項。

API 如何處理多個條碼?

中展示了三種不同的條碼格式,分別標記為 ABC,包括 QR 碼、Code128 和 DataMatrix 碼,IronBarcode 可在生產環境中同時處理這三種條碼格式。

IronBarcode 一次呼叫即可處理單一影像中的多個條碼,並傳回一個結果陣列。 回應中的每個條目都包含位置數據,以便客戶端應用程式可以在螢幕上突出顯示偵測到的條碼。

瀏覽器開發者工具的網路標籤顯示成功的 JSON API 回應,其中包含一個數組,該數組包含三個檢測到的條碼以及完整的元數據,包括類型、值、置信度和位置座標。

結構化的 JSON 回應為客戶端應用程式提供了處理和顯示條碼結果所需的一切,無需額外的查找。

如何處理具有挑戰性的條碼影像?

現實世界中的條碼掃描經常會遇到不完美的影像——例如拍攝角度不當、光線不足或條碼部分損壞等情況。 IronBarcode 透過其先進的影像處理能力機器學習置信度閾值來解決這些問題。

診斷常見掃描問題

在進行修正之前,請先確定您的問題屬於哪一類。 生產中的大多數掃描失敗可歸為以下五個類別之一:影像品質問題(模糊、雜訊、解析度低)、幾何問題(旋轉、傾斜、透視變形)、損壞問題(標籤撕裂、墨跡污損)、環境問題(眩光、陰影、照明不一致)以及誤報偵測(讀取器找到不存在的條碼)。

了解類別有助於選擇合適的濾鏡組合和讀取速度,而無需對每張影像進行不必要的處理。 對於大多數 Web 應用程式場景,以 ReadingSpeed.BalancedAutoRotate = true 開頭即可涵蓋大多數情況。 只有當第一次嘗試沒有回傳任何結果時,才升級到 ExtremeDetail

下面的程式碼中的多遍方法實作了這種分層策略。 快速的第一遍掃描能夠快速處理典型影像,在常見情況下保持較低的平均延遲。 只有當第一次審核失敗時才會觸發第二次審核,從而確保您只在真正需要時才支付額外的處理費用。 這種模式可以確保 ASP.NET 端點在正常負載下保持回應,同時也能可靠地處理棘手的極端情況。

條碼掃描常見問題及解決方案
問題 症狀 解決方案
模糊影像 置信度低,讀取錯誤。 應用SharpenFilter ,提高ExtremeDetail速度
旋轉條碼 完全未偵測到條碼 啟用AutoRotate = true
條碼損壞 部分讀取,錯誤值 啟用錯誤修正,使用RemoveFalsePositive
對比差 檢測結果不一致 應用ContrastFilterBrightnessFilter
效能太慢 上傳延遲高 使用ReadingSpeed.Faster ,啟用多執行緒

實現多遍影像處理

對於複雜影像,分層處理方法可以在不犧牲簡單影像處理效能的前提下,獲得最佳處理效果:

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

BarcodeReaderOptions類別可以對掃描的各個方面進行精細控制。 設定 AutoRotate 可處理以任何角度拍攝的影像,而影像濾鏡可提高模糊或低對比度條碼的清晰度。 如需詳細配置,請參閱條碼閱讀器設定範例PDF 特定閱讀器設定

處理 PDF 文件時,可以考慮在 PDF 文件上添加條碼,或將條碼建立為 PDF 文件。 對於大批量處理,透過非同步和多執行緒功能啟用多執行緒可以顯著提高吞吐量。

新增瀏覽器相容性和回退策略

支援多種瀏覽器需要逐步增強。 Android 和桌面版 Chrome、Edge 和 Firefox 等現代瀏覽器支援 MediaDevices.getUserMedia() API 以存取攝影機。 iOS 版 Safari 從 11 版本開始支援此功能。 較舊的企業瀏覽器、IE11 相容模式以及某些受限的企業環境可能完全不支援攝影機訪問,因此您的備用檔案上傳路徑必須始終保持可用狀態。

建議採用運行時特徵檢測而不是用戶代理嗅探,然後相應地顯示或隱藏相機介面。 首先提供具備相機功能的介面,然後優雅地回退到檔案上傳模式:

@* 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

如果您偏好基於元件的方法, Blazor 整合可提供現代 Web 應用程式支持,且配置極少。 如需排查部署問題,請參閱執行時期複製異常指南

下一步計劃是什麼?

使用 IronBarcode,在 ASP.NET 中進行條碼掃描變得非常簡單。 您只需安裝一個 NuGet 包,調用 BarcodeReader.Read(),即可獲得 30 多種格式的可靠解碼結果,包括其他庫難以處理的具有挑戰性的真實世界圖像。

為了在此基礎上繼續發展,請探索以下資源:

條碼讀取教學課程-涵蓋所有掃描場景的詳細指南 條碼產生-以程式設計方式建立條碼和二維碼 -二維碼產生器-- 二維碼特有的功能與樣式 影像校正-提高複雜影像掃描精度的技術 -非同步和多執行緒-擴展條碼處理能力,以應對高流量應用 -跨平台相容性-可部署在 Windows、Linux、Docker、Azure 和 AWS 上 -支援的條碼格式-- 可讀取和可寫條碼格式的完整列表 -容錯特性-在惡劣條件下可靠運行 API 參考-- 所有類別和選項的完整文檔 -授權選項-SaaS、OEM 和企業級許可,適用於生產部署

首先取得免費試用許可證,即可在您的 ASP.NET 應用程式中無限制地測試 IronBarcode。 試用版包含對所有功能的完整存取權限,包括多格式檢測、圖像校正以及本指南中所示的 REST API 模式——因此您可以在購買生產許可證之前,在自己的圖像上評估效能。 如需需要裝置端掃描的 .NET MAUI 行動應用,請參閱.NET MAUI 條碼掃描器教學課程,該教學將相同的 API 擴展到 iOS 和 Android 目標平台。

常見問題解答

條碼掃描在 ASP.NET 應用程式中的主要用途是什麼?

條碼掃描在 ASP.NET 應用程式中的主要用於增強庫存管理系統、在活動中處理門票和數字化紙質文件,從而提高效率並減少錯誤。

IronBarcode 如何促進 ASP.NET 中的條碼掃描?

IronBarcode 通過提供可以輕鬆集成到網頁應用程式中的可靠且高效的組件,簡化了 ASP.NET 中的條碼掃描過程,允許開發者快速實現掃描功能。

IronBarcode 可以掃描哪些類型的條碼?

IronBarcode 支持掃描多種條碼格式,包括傳統的線性條碼和現代的二維條碼,確保與多樣化的應用程序兼容。

IronBarcode 能否處理文件處理的條碼掃描?

是的,IronBarcode 非常適合文件處理工作流程,可以用來掃描嵌入的條碼以數字化和組織紙質文件。

IronBarcode 是否適合庫存管理系統?

IronBarcode 是庫存管理系統的極佳選擇,因為它可以通過掃描條碼來高效跟踪產品,從而簡化操作並減少錯誤。

集成 IronBarcode 如何改善活動門票處理?

通過集成 IronBarcode,活動門票處理變得無縫,因為它允許快速掃描門票條碼,從而促進事件中快速準確的入場管理。

在 ASP.NET 專案中使用 IronBarcode 有哪些優勢?

在 ASP.NET 專案中使用 IronBarcode 提供了多種優勢,包括易於集成、多條碼格式支持,以及增強的應用程式性能,從而為條碼掃描需求提供了強大的解決方案。

實施 IronBarcode 是否需要廣泛的編碼知識?

不,IronBarcode 的設計以開發者為導向,使得在 ASP.NET 應用程式中實現條碼掃描功能變得簡單,僅需最低限度的編碼知識。

IronBarcode 能否用於移動網頁應用程式?

是的,IronBarcode 可以集成到移動網頁應用程式中,允許隨時隨地的條碼掃描,提升了 ASP.NET 專案的多功能性。

Jordi Bardia
軟體工程師
Jordi 在 Python、C# 和 C++ 上最得心應手,當他不在 Iron Software 展現技術時,便在做遊戲編程。在分担產品测测试,產品開發和研究的责任時,Jordi 為持续的產品改進增值。他说这种多样化的经验使他受到挑战并保持参与, 而这也是他与 Iron Software 中工作一大乐趣。Jordi 在佛罗里达州迈阿密长大,曾在佛罗里达大学学习计算机科学和统计学。

鋼鐵支援團隊

我們每週 5 天,每天 24 小時在線上。
聊天
電子郵件
打電話給我