跳至頁尾內容
使用IRONBARCODE
如何在C#中構建ASP .NET條碼掃描器 | IronBarcode

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

在ASP.NET中使用IronBarcode進行條碼掃描變得簡單:通過NuGet安裝,調用BarcodeReader.Read(),並在一個步驟中獲取型別、置信度和位置資訊的解碼值——不需要複雜的配置。

條碼掃描是現代Web應用程式中的標準需求,支持庫存管理、文件處理和票務驗證的工作流程。 根據GS1,全球每天有超過60億宗交易使用條碼——這一數字突顯出準確的條碼讀取對於任何商業系統而言是多麼關鍵。 ISO/IEC 15415標準定義了2D條碼符號的質量指標,而ISO/IEC 15416標準涵蓋了1D線性條碼,IronBarcode均原生支持這兩者。

本指南將向您展示如何使用IronBarcode將可靠的條碼掃描新增到您的ASP.NET Core應用程式中,涵蓋了安裝,文件上傳處理,REST API整合和生產部署模式。 到最後,您將擁有一個Razor頁面文件上傳掃描器和一個接受來自任何客戶端的base64編碼圖像的JSON API端點的工作程式碼。

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

入門僅需幾分鐘。 該程式庫支持ASP.NET Core和傳統的ASP.NET MVC應用程式,使其適應於各種專案型別。企業部署在AzureAWS LambdaDocker容器上也同樣可以正常運行。 該程式庫的機器學習驅動檢測通過自動應用高級圖像校正來處理具有挑戰性的條碼圖像,這在處理在變化光照條件下使用手機相機拍攝的照片時特別有用。

通過NuGet套件管理器安裝

在Visual Studio中打開套件管理器控制臺並運行:

Install-Package BarCode

或者,使用.NET CLI:

dotnet add package BarCode

或者在Visual Studio的NuGet套件管理器UI中搜尋"BarCode"並點擊安裝。 該套件會自動管理所有依賴項。

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

配置您的專案

安裝後,將必要的using語句新增到您的C#檔案中:

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

此引用使您能夠存取IronBarcode的完整條碼讀取生成功能。 該程式庫支持超過30種條碼格式,包括QR Code、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

伺服器端方法可讓您最大限度地控制圖像處理,並在所有瀏覽器上保持一致性。 當伺服器處理每個圖像時,您還可以獲得一個乾淨的審計軌跡:每個掃描的條碼都會通過您的應用層,您可以在那裡記錄它,將其與資料庫進行驗證,或觸發下游工作流程。 這種模式特別適合於高需求行業,如醫療、物流和製造業,在這些行業中,每項掃描必須被記錄。

對於客戶端相機捕獲整合,現代瀏覽器支持用於相機存取的MediaDevicesAPI,該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和GIF以及PDF文件,消除了格式特定處理程式碼。

掃描輸入和輸出如何

編碼URL 'https://ironsoftware.com/csharp/barcode/'的Code 128條碼,展示可機器讀取的條紋和人類可讀的文字,以便在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傳輸
  • CORS政策:限制哪些來源可以調用您的掃描端點
  • 授權密鑰管理正確應用授權密鑰,並在生產中配置它們在web.config

構建生產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如何處理多個條碼?

三種不同的條碼格式標有A B C,展示了IronBarcode在生產環境中同時處理的QR Code Code128和DataMatrix符號

IronBarcode在一次調用中處理一個圖像中的多個條碼,返回一個結果陣列。 每個響應中的條目都包括位置資料,這樣客戶端應用可以在螢幕上突出顯示檢測到的條碼。

瀏覽器開發者工具網路選項卡顯示成功的JSON API響應,包含三個檢測到的條碼的陣列,完整元資料包括型別、值、置信度和位置座標

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

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

實際的條碼掃描經常涉及不完美的圖像——那些拍攝時有角度、光照不佳或部分損壞的條碼。 IronBarcode通過其先進的圖像處理功能機器學習置信度門檻來應對這些情況。

診斷常見的掃描問題

在應用更正之前,識別您的問題型別歸屬哪一類。 大多數生產中的掃描失敗都屬於五個組中的一個:圖像質量問題(模糊、噪聲、低解析度)、幾何問題(旋轉、傾斜、透視畸變)、損壞問題(撕裂的標籤、墨水模糊)、環境問題(眩光、陰影、不一致的光照)和假陰性檢測,讀取器讀到了不存在的條碼。

瞭解類別可以幫助您選擇正確的過濾器組合和讀取速度,而不是對每個圖像進行不必要的處理。 對於大多數Web應用場景,從AutoRotate = 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應用支持,僅需最小配置。 如需部署故障排除,請參阅運行時複製異常指南

您的下一步是什麼?

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

要繼續在此基礎上構建,請探索這些資源:

免費試用授權開始,無限制地在您的ASP.NET應用程式中測試IronBarcode。 試用包括對所有功能的完整存取,包括多格式檢測、圖像校正和此指南中展示的REST API模式——讓您在發佈到生產環境授權之前先在自己的圖像上評估性能。 對於需要裝置上掃描的.NET MAUI移動應用,請參阅.NET MAUI條碼掃描器教程,該教程將同一API擴展到iOS和Android目標。

常見問題

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

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

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

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

可以使用IronBarcode掃描哪些型別的條碼?

IronBarcode支持掃描多種條碼格式,包括傳統的線性條碼和現代的2D條碼,確保與多樣的應用相容。

IronBarcode可以處理文件處理的條碼掃描嗎?

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

IronBarcode適合用於庫存管理系統嗎?

IronBarcode是一個優秀的庫存管理系統選擇,因為它能夠通過掃描條碼高效追蹤產品,從而精簡操作並最小化錯誤。

整合IronBarcode如何改善活動票務處理?

通過整合IronBarcode,活動票務處理變得更無縫,因為它允許快速掃描門票條碼,方便活動中的快速準確入場管理。

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

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

IronBarcode的實施需要豐富的編程知識嗎?

不,IronBarcode設計為易於開發者使用,使其能在ASP.NET應用程式中輕鬆實現條碼掃描功能,而不需要豐富的編程知識。

IronBarcode可以用於移動網頁應用程式嗎?

是的,IronBarcode可以整合到移動網頁應用程式中,允許隨時隨地進行條碼掃描,提高ASP.NET專案的靈活性。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

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