跳過到頁腳內容
使用 IRONBARCODE

ASP.NET 條碼掃描器教學:C# 條碼產生器指南

使用 IronBarcode 的高效能函式庫在 ASP.NET Web 應用程式中實作條碼掃描。 它支援 30 多種格式,能夠處理真實世界的映像條件,並為 Windows、Linux 和雲端部署提供檔案上傳和 REST API 整合方法。

IronBarcode 可透過檔案上傳或 REST API 在 ASP.NET 中實現條碼掃描,支援 30 多種格式,並具有先進的影像處理功能,可在 Windows、Linux 和雲端平台上處理真實世界的影像。

條碼掃描已成為現代網路應用程式的必備功能,為從庫存管理到文件處理工作流程的方方面面提供支援。 無論您是追蹤產品、處理票據或將紙本文件數位化,在 ASP.NET Web 應用程式中實施可靠的條碼掃描都能顯著提高效率並減少錯誤。

IronBarcode 為 .NET 應用程式中讀取產生條碼提供了一個有效且簡單的解決方案。 與其他需要複雜配置或難以處理真實影像的函式庫不同,IronBarcode 只需極少的設定即可提供精準的結果。其跨平台相容性確保您的 Web 應用程式無論部署在 Windows、Linux 或雲端容器上都能流暢運行,而其基於機器學習的偵測功能則能透過先進的影像校正濾鏡將條碼影像轉換為機器可讀格式,從而輕鬆應對各種挑戰性條碼影像。

如何在 ASP.NET 中將 IronBarcode 設為條碼讀取器?

使用 IronBarcode 入門只需幾分鐘。 該程式庫同時支援 ASP.NET Core 和傳統的 ASP.NET MVC 應用程序,使其能夠靈活應用於各種專案類型。對於企業級部署,IronBarcode 可以與AzureAWS Lambda環境以及Docker 容器無縫集成,從而支援容器化應用程式。 該庫的容錯功能確保即使在具有挑戰性的條件下也能可靠運行,而演示則展示了現實世界的應用。

為什麼選擇 IronBarcode 而不是開源替代方案?

在評估條碼庫時,您通常會考慮 ZXing.NET、 BarcodeLibSkiaSharp等開源選項。 然而,IronBarcode 具有一些獨特的優勢,足以證明其商業授權的合理性:

效能基準測試:在生產環境中,IronBarcode 處理條碼的速度比 ZXing.NET 快 3-5 倍,尤其是在處理損壞或旋轉的影像時。 它的多執行緒支援與 CPU 核心數呈線性關係,而大多數開源替代方案都是單執行緒的。 非同步和多執行緒功能可以同時有效率地處理多個條碼。

影像品質處理:與需要完美條碼影像的 ZXing 不同,IronBarcode 的 ML 引擎能夠準確讀取從角度拍攝、光線不足或部分損壞的照片中讀取的條碼。 內建的影像校正方向校正功能省去了其他庫所需的預處理步驟。

企業支援:商業許可包括專屬支援、定期更新和專業服務等級協定 (SLA)。 開源專案依賴社群支持,無法保證回應時間和錯誤修復。 工程請求系統確保技術問題及時解決。

API 簡潔性:使用 IronBarcode 讀取條碼只需要一行程式碼,而開源替代方案實作相同功能則需要 10-20 行程式碼。 這意味著更快的開發速度和更低的維護成本。 查看條碼快速入門範例,了解其簡易性。

有哪些安裝方法?

首先,使用 NuGet 套件管理器控制台安裝 IronBarcode:

Install-Package BarCode
Install-Package BarCode
SHELL

或者,透過 Visual Studio 的 NuGet 套件管理器 UI 進行安裝,搜尋"IronBarCode"並按一下"安裝"。 該軟體包會自動管理所有相依性。 對於特定平台的部署,請考慮使用針對目標環境進行最佳化的特定平台 NuGet 套件。 該程式庫提供標準版和BarCode.Slim 版,以適應不同的部署場景。 有關詳細的安裝指導,請查看IronBarcode 安裝指南

如何在專案中配置 IronBarcode?

安裝完成後,將必要的 using 語句新增至您的 C# 條碼讀取器檔案:

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

透過簡單的匯入,您可以存取 IronBarcode 的完整條碼讀取產生功能。 本函式庫支援超過 30 種條碼格式,包括二維碼產生、Code 128、Code 39、Data Matrix 和 PDF417。查看支援的條碼格式完整清單以確保相容性。 該庫的功能集包括樣式選項閱讀增強等高級功能。 根據微軟關於 ASP.NET 的文檔,正確的套件管理對於維護應用程式的安全性至關重要。 如需故障排除,請參閱NuGet 套件故障排除指南或提交工程支援請求以獲得專門支援。

哪些架構模式最適合基於 Web 的掃描?

在 ASP.NET 應用程式中實作條碼掃描時,主要有兩種架構方法。 了解這些規則有助於您針對每種使用情境選擇合適的條碼閱讀器設定。 該庫提供完整的輸出資料格式,以滿足各種架構需求:

// Server-side processing architecture
public class BarcodeService
{
    private readonly ILogger<BarcodeService> _logger;

    public async Task<BarcodeResult> ProcessUploadedImage(IFormFile file)
    {
        using var stream = file.OpenReadStream();
        var options = new BarcodeReaderOptions
        {
            Speed = ReadingSpeed.Balanced,
            ExpectMultipleBarcodes = true,
            // Enable ML confidence threshold
            UseConfidenceThreshold = true,
            ConfidenceThreshold = 0.85
        };

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

        return new BarcodeResult
        {
            Barcodes = results.Select(r => new ScannedBarcode
            {
                Type = r.BarcodeType.ToString(),
                Value = r.Text,
                Confidence = r.Confidence
            }).ToList()
        };
    }
}
// Server-side processing architecture
public class BarcodeService
{
    private readonly ILogger<BarcodeService> _logger;

    public async Task<BarcodeResult> ProcessUploadedImage(IFormFile file)
    {
        using var stream = file.OpenReadStream();
        var options = new BarcodeReaderOptions
        {
            Speed = ReadingSpeed.Balanced,
            ExpectMultipleBarcodes = true,
            // Enable ML confidence threshold
            UseConfidenceThreshold = true,
            ConfidenceThreshold = 0.85
        };

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

        return new BarcodeResult
        {
            Barcodes = results.Select(r => new ScannedBarcode
            {
                Type = r.BarcodeType.ToString(),
                Value = r.Text,
                Confidence = r.Confidence
            }).ToList()
        };
    }
}
Imports System.Threading.Tasks

' Server-side processing architecture
Public Class BarcodeService
    Private ReadOnly _logger As ILogger(Of BarcodeService)

    Public Async Function ProcessUploadedImage(file As IFormFile) As Task(Of BarcodeResult)
        Using stream = file.OpenReadStream()
            Dim options As New BarcodeReaderOptions With {
                .Speed = ReadingSpeed.Balanced,
                .ExpectMultipleBarcodes = True,
                .UseConfidenceThreshold = True,
                .ConfidenceThreshold = 0.85
            }

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

            Return New BarcodeResult With {
                .Barcodes = results.Select(Function(r) New ScannedBarcode With {
                    .Type = r.BarcodeType.ToString(),
                    .Value = r.Text,
                    .Confidence = r.Confidence
                }).ToList()
            }
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

這種伺服器端方法可以最大限度地控制影像處理,並且在所有瀏覽器上都能穩定運作。 對於客戶端擷取集成,現代瀏覽器支援MediaDevices API 進行攝影機訪問,這可以與 IronBarcode 的REST API 處理讀取速度最佳化相結合。 考慮採用非同步和多執行緒技術以提高效能。 該庫的API 參考文檔提供了所有可用選項的詳細文件。

何時應該使用客戶端處理,何時該使用伺服器端處理?

選擇客戶端捕獲資料並由伺服器端處理還是純伺服器端實現,取決於以下幾個因素:

客戶端捕獲 + 伺服器端處理

  • 非常適合即時掃描場景
  • 透過在上傳前進行裝置端處理來減少頻寬佔用
  • 需要現代瀏覽器支援
  • 透過即時回饋提升使用者體驗
  • 考慮非同步條碼讀取以提高效能

純伺服器端處理

  • 最大程度相容於所有設備
  • 對處理流程的完全控制
  • 更適用於多條碼讀取的批次處理場景
  • 簡化的安全模型
  • 支援從流中讀取數據,以提高記憶體效率

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

ASP.NET Web 應用程式中最常見的條碼掃描場景是使用者上傳包含條碼的圖像。 此方案非常適合處理發票、貨運標籤或任何帶有嵌入式條碼的文件。 為了提高效能,可以考慮採用非同步條碼讀取來同時處理多個上傳任務。 您還可以探索從資料流中讀取條碼以提高記憶體使用效率。 該函式庫能夠有效處理多種條碼讀取場景,非常適合批次處理。 有關具體實作方法,請查看條碼快速入門範例

哪些HTML結構支援更有效率的文件上傳?

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

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

<script>
// Progressive enhancement for modern browsers
if ('mediaDevices' in navigator) {
    document.getElementById('barcodeFile')
        .setAttribute('accept', 'image/*,.pdf,capture=camera');
}

// Show loading state
document.getElementById('barcodeForm').addEventListener('submit', function() {
    const spinner = document.querySelector('.spinner-border');
    spinner.classList.remove('d-none');
    document.getElementById('scanBtn').disabled = true;
});
</script>
<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>

<script>
// Progressive enhancement for modern browsers
if ('mediaDevices' in navigator) {
    document.getElementById('barcodeFile')
        .setAttribute('accept', 'image/*,.pdf,capture=camera');
}

// Show loading state
document.getElementById('barcodeForm').addEventListener('submit', function() {
    const spinner = document.querySelector('.spinner-border');
    spinner.classList.remove('d-none');
    document.getElementById('scanBtn').disabled = true;
});
</script>
The provided code is HTML and JavaScript, not C#. Therefore, it doesn't require conversion to VB.NET. If you have any C# code that needs conversion, please provide it, and I'll be happy to assist.
$vbLabelText   $csharpLabel

如何實現安全的後端處理?

現在實作具有安全驗證的後端控制器,並改進 ASP.NET 條碼閱讀器的處理,使用輸出資料格式以靈活地處理結果。 考慮實施誤報預防GS1-128 支持,以滿足特殊條碼需求:

[HttpPost]
[ValidateAntiForgeryToken]
[RequestSizeLimit(10_000_000)] // 10MB limit
public async Task<IActionResult> ScanBarcode(IFormFile barcodeFile)
{
    // Security: Validate file type
    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;

            // Configure reader for improved web performance
            var options = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Balanced,
                ExpectMultipleBarcodes = true,
                // Set specific barcode types for faster processing
                ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional | 
                                    BarcodeEncoding.QRCode | 
                                    BarcodeEncoding.DataMatrix,
                ImageFilters = new ImageFilterCollection
                {
                    new SharpenFilter(),
                    new ContrastFilter()
                }
            };

            // Read barcode from the uploaded image
            var results = BarcodeReader.Read(stream, options);

            if (results.Any())
            {
                ViewBag.BarcodeResult = string.Join("<br/>", 
                    results.Select(r => $"<strong>{r.BarcodeType}:</strong> {r.Text}"));
            }
            else
            {
                ViewBag.BarcodeResult = "No barcodes found in the image.";
            }
        }
    }
    return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
[RequestSizeLimit(10_000_000)] // 10MB limit
public async Task<IActionResult> ScanBarcode(IFormFile barcodeFile)
{
    // Security: Validate file type
    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;

            // Configure reader for improved web performance
            var options = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Balanced,
                ExpectMultipleBarcodes = true,
                // Set specific barcode types for faster processing
                ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional | 
                                    BarcodeEncoding.QRCode | 
                                    BarcodeEncoding.DataMatrix,
                ImageFilters = new ImageFilterCollection
                {
                    new SharpenFilter(),
                    new ContrastFilter()
                }
            };

            // Read barcode from the uploaded image
            var results = BarcodeReader.Read(stream, options);

            if (results.Any())
            {
                ViewBag.BarcodeResult = string.Join("<br/>", 
                    results.Select(r => $"<strong>{r.BarcodeType}:</strong> {r.Text}"));
            }
            else
            {
                ViewBag.BarcodeResult = "No barcodes found in the image.";
            }
        }
    }
    return View();
}
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
Imports System.Linq

<HttpPost>
<ValidateAntiForgeryToken>
<RequestSizeLimit(10_000_000)> ' 10MB limit
Public Async Function ScanBarcode(barcodeFile As IFormFile) As Task(Of IActionResult)
    ' Security: Validate file type
    Dim allowedExtensions = {".jpg", ".jpeg", ".png", ".gif", ".tiff", ".bmp", ".pdf"}
    Dim extension = 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

            ' Configure reader for improved web performance
            Dim options As New BarcodeReaderOptions With {
                .Speed = ReadingSpeed.Balanced,
                .ExpectMultipleBarcodes = True,
                ' Set specific barcode types for faster processing
                .ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional Or
                                      BarcodeEncoding.QRCode Or
                                      BarcodeEncoding.DataMatrix,
                .ImageFilters = New ImageFilterCollection From {
                    New SharpenFilter(),
                    New ContrastFilter()
                }
            }

            ' Read barcode from the uploaded image
            Dim results = BarcodeReader.Read(stream, options)

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

該實作透過將上傳的文件複製到記憶體流來處理這些文件,然後使用 IronBarcode 的BarcodeReader.Read方法來提取所有條碼。 此方法可自動偵測條碼格式並傳回詳細結果。 IronBarcode 可以處理各種影像格式,包括多頁 TIFF 和 GIF ,甚至PDF 文檔,從而無需編寫特定於格式的處理代碼。 為了提高精度,可以探索影像校正技術方向校正方法。 該庫的功能還包括創建條碼圖像保存條碼輸出。 這種多功能性使其成為Stack Overflow 條碼實現主題中討論的文檔處理場景的理想選擇。 有關具體條碼類型,請參閱閱讀 Code 39 條碼Code 39 範例

輸入的條碼影像是什麼樣的?

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

以上範例展示了 IronBarcode 能夠高效處理的典型 Code 128 條碼,即使影像品質有所變化,也能保持準確性。

條碼掃描器回傳什麼結果?

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

IronBarcode 會傳回完整的元數據,包括條碼類型、解碼值、置信度分數以及每個偵測到的條碼的位置資料。 ## 如何建立用於條碼或二維碼掃描的 REST API?

現代 ASP.NET Web 應用程式通常需要透過 REST API 提供條碼掃描功能,以便與行動應用程式、SPA 或第三方服務整合。 此方法支援客戶端攝影機擷取和伺服器端處理。 此庫的條碼建立功能與其讀取功能相輔相成,可提供完整的條碼解決方案。 以下是如何使用 ASP.NET Core 建立一個可靠的、可用於生產的條碼掃描器 API ,並具備匯出到串流的功能。 對於二維碼的特定應用,請探索建立二維碼自訂二維碼樣式

條碼 API 需要考慮哪些安全性因素?

實作條碼掃描 API 需要格外注意安全性,尤其是在處理條碼中編碼的敏感資料時。 請遵循IronBarcode 安全指南以獲得全面保護:

輸入驗證:始終驗證傳入資料以防止注入攻擊。 條碼若未進行適當清理,可能包含惡意載重。

速率限制:實作請求節流以防止 API 濫用和拒絕服務攻擊。 考慮使用 ASP.NET Core 內建的速率限制中間件。

身份驗證與授權:使用適當的身份驗證機制(例如 JWT 令牌或 API 金鑰)來保護 API 端點。 正確應用許可證密鑰以進行生產部署。

資料加密:所有 API 通訊應使用 HTTPS,並考慮對靜態儲存的敏感條碼資料進行加密。對於 Web 應用程序,請在 web.config 檔案中安全地設定許可證金鑰

CORS 設定:仔細設定跨網域資源共用 (CORS) 策略,以防止未經授權的網域存取您的 API。

如何建立可用於生產環境的條碼 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
        {
            // Input validation
            if (string.IsNullOrEmpty(request.ImageBase64))
                return BadRequest(new ErrorResponse { Error = "Image data is required" });

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

            // Convert base64 string to byte array
            byte[] imageBytes = Convert.FromBase64String(request.ImageBase64);

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

            // Configure reader for API usage
            var options = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Faster, // Improve for API response time
                ExpectMultipleBarcodes = request.ExpectMultiple ?? false,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.8
            };

            // Read barcodes from the image
            var results = await Task.Run(() => BarcodeReader.Read(imageBytes, options));

            var response = new BarcodeResponse
            {
                Success = true,
                ProcessingTimeMs = 0, // Would be set by middleware
                Barcodes = results.Select(r => new BarcodeData
                {
                    Type = r.BarcodeType.ToString(),
                    Value = r.Text,
                    Confidence = r.Confidence,
                    Format = r.BarcodeType.ToString().ToLower(),
                    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 successful results for 5 minutes
            _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" });
        }
    }

    [HttpPost("scan-stream")]
    public async Task<IActionResult> ScanBarcodeStream()
    {
        // Alternative endpoint for direct file uploads
        var file = Request.Form.Files.FirstOrDefault();
        if (file == null)
            return BadRequest(new ErrorResponse { Error = "No file uploaded" });

        using var stream = file.OpenReadStream();
        var results = BarcodeReader.Read(stream);

        return Ok(new BarcodeResponse
        {
            Success = true,
            Barcodes = results.Select(r => new BarcodeData
            {
                Type = r.BarcodeType.ToString(),
                Value = r.Text
            }).ToList()
        });
    }
}

public class BarcodeRequest
{
    public string ImageBase64 { get; set; }
    public bool? ExpectMultiple { get; set; }
}

public class BarcodeResponse
{
    public bool Success { get; set; }
    public List<BarcodeData> Barcodes { get; set; }
    public int ProcessingTimeMs { get; set; }
}

public class BarcodeData
{
    public string Type { get; set; }
    public string Value { get; set; }
    public double Confidence { get; set; }
    public string Format { get; set; }
    public BarcodePosition Position { get; set; }
}

public class BarcodePosition
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
}

public class ErrorResponse
{
    public bool Success => false;
    public string Error { get; set; }
}
[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
        {
            // Input validation
            if (string.IsNullOrEmpty(request.ImageBase64))
                return BadRequest(new ErrorResponse { Error = "Image data is required" });

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

            // Convert base64 string to byte array
            byte[] imageBytes = Convert.FromBase64String(request.ImageBase64);

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

            // Configure reader for API usage
            var options = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Faster, // Improve for API response time
                ExpectMultipleBarcodes = request.ExpectMultiple ?? false,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.8
            };

            // Read barcodes from the image
            var results = await Task.Run(() => BarcodeReader.Read(imageBytes, options));

            var response = new BarcodeResponse
            {
                Success = true,
                ProcessingTimeMs = 0, // Would be set by middleware
                Barcodes = results.Select(r => new BarcodeData
                {
                    Type = r.BarcodeType.ToString(),
                    Value = r.Text,
                    Confidence = r.Confidence,
                    Format = r.BarcodeType.ToString().ToLower(),
                    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 successful results for 5 minutes
            _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" });
        }
    }

    [HttpPost("scan-stream")]
    public async Task<IActionResult> ScanBarcodeStream()
    {
        // Alternative endpoint for direct file uploads
        var file = Request.Form.Files.FirstOrDefault();
        if (file == null)
            return BadRequest(new ErrorResponse { Error = "No file uploaded" });

        using var stream = file.OpenReadStream();
        var results = BarcodeReader.Read(stream);

        return Ok(new BarcodeResponse
        {
            Success = true,
            Barcodes = results.Select(r => new BarcodeData
            {
                Type = r.BarcodeType.ToString(),
                Value = r.Text
            }).ToList()
        });
    }
}

public class BarcodeRequest
{
    public string ImageBase64 { get; set; }
    public bool? ExpectMultiple { get; set; }
}

public class BarcodeResponse
{
    public bool Success { get; set; }
    public List<BarcodeData> Barcodes { get; set; }
    public int ProcessingTimeMs { get; set; }
}

public class BarcodeData
{
    public string Type { get; set; }
    public string Value { get; set; }
    public double Confidence { get; set; }
    public string Format { get; set; }
    public BarcodePosition Position { get; set; }
}

public class BarcodePosition
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
}

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

<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
            ' Input validation
            If String.IsNullOrEmpty(request.ImageBase64) Then
                Return BadRequest(New ErrorResponse With {.Error = "Image data is required"})
            End If

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

            ' Convert base64 string to byte array
            Dim imageBytes As Byte() = Convert.FromBase64String(request.ImageBase64)

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

            ' Configure reader for API usage
            Dim options As New BarcodeReaderOptions With {
                .Speed = ReadingSpeed.Faster, ' Improve for API response time
                .ExpectMultipleBarcodes = request.ExpectMultiple.GetValueOrDefault(False),
                .UseConfidenceThreshold = True,
                .ConfidenceThreshold = 0.8
            }

            ' Read barcodes from the image
            Dim results = Await Task.Run(Function() BarcodeReader.Read(imageBytes, options))

            Dim response As New BarcodeResponse With {
                .Success = True,
                .ProcessingTimeMs = 0, ' Would be set by middleware
                .Barcodes = results.Select(Function(r) New BarcodeData With {
                    .Type = r.BarcodeType.ToString(),
                    .Value = r.Text,
                    .Confidence = r.Confidence,
                    .Format = r.BarcodeType.ToString().ToLower(),
                    .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 successful results for 5 minutes
            _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

    <HttpPost("scan-stream")>
    Public Async Function ScanBarcodeStream() As Task(Of IActionResult)
        ' Alternative endpoint for direct file uploads
        Dim file = Request.Form.Files.FirstOrDefault()
        If file Is Nothing Then
            Return BadRequest(New ErrorResponse With {.Error = "No file uploaded"})
        End If

        Using stream = file.OpenReadStream()
            Dim results = BarcodeReader.Read(stream)

            Return Ok(New BarcodeResponse With {
                .Success = True,
                .Barcodes = results.Select(Function(r) New BarcodeData With {
                    .Type = r.BarcodeType.ToString(),
                    .Value = r.Text
                }).ToList()
            })
        End Using
    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)
    Public Property ProcessingTimeMs As Integer
End Class

Public Class BarcodeData
    Public Property Type As String
    Public Property Value As String
    Public Property Confidence As Double
    Public Property Format As String
    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

此 API 介面接受 base64 編碼的映像,這是一種用於透過 HTTP 傳輸映像的標準格式。回應包含完整的條碼訊息,包括置信度評分和位置資料。 該實現遵循RESTful 最佳實踐,確保與任何前端框架無縫整合。 對於大批量應用場景,可考慮實施批次條碼處理讀取速度最佳化。 該程式庫的授權選項包括對 API 部署的企業級支持,以及用於擴展的升級路徑擴充功能

有哪些客戶端實現方案?

以下 JavaScript 程式碼示範了現代用戶端與相機拍攝的集成,可與非同步條碼讀取一起使用。 如需更多條碼產生功能,請探索自訂條碼樣式以及從各種資料來源建立條碼

// Modern JavaScript client with camera support
class BarcodeScanner {
    constructor(apiEndpoint = '/api/barcode/scan') {
        this.apiEndpoint = apiEndpoint;
        this.videoElement = null;
        this.canvasElement = null;
    }

    // Initialize camera for live capture
    async initializeCamera(videoElementId) {
        this.videoElement = document.getElementById(videoElementId);

        try {
            const stream = await navigator.mediaDevices.getUserMedia({
                video: { 
                    facingMode: 'environment', // Use rear camera on mobile
                    width: { ideal: 1280 },
                    height: { ideal: 720 }
                }
            });
            this.videoElement.srcObject = stream;

            // Create canvas for capturing frames
            this.canvasElement = document.createElement('canvas');
            this.canvasElement.width = 1280;
            this.canvasElement.height = 720;

            return true;
        } catch (error) {
            console.error('Camera initialization failed:', error);
            return false;
        }
    }

    // Capture frame and scan
    async captureAndScan() {
        if (!this.videoElement || !this.canvasElement) {
            throw new Error('Camera not initialized');
        }

        const context = this.canvasElement.getContext('2d');
        context.drawImage(this.videoElement, 0, 0, 
                         this.canvasElement.width, 
                         this.canvasElement.height);

        // Convert to base64
        const imageData = this.canvasElement.toDataURL('image/jpeg', 0.8);
        const base64 = imageData.split(',')[1];

        // Send to API
        const response = await fetch(this.apiEndpoint, {
            method: 'POST',
            headers: { 
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest' // CSRF protection
            },
            body: JSON.stringify({ 
                imageBase64: base64,
                expectMultiple: true 
            })
        });

        if (!response.ok) {
            throw new Error(`API error: ${response.statusText}`);
        }

        return await response.json();
    }

    // Scan from file upload with progress
    async scanFile(file, progressCallback) {
        const base64 = await this.fileToBase64(file);

        const xhr = new XMLHttpRequest();

        return new Promise((resolve, reject) => {
            xhr.upload.addEventListener('progress', (e) => {
                if (progressCallback && e.lengthComputable) {
                    progressCallback(Math.round((e.loaded / e.total) * 100));
                }
            });

            xhr.addEventListener('load', () => {
                if (xhr.status === 200) {
                    resolve(JSON.parse(xhr.responseText));
                } else {
                    reject(new Error(`Server error: ${xhr.status}`));
                }
            });

            xhr.addEventListener('error', () => reject(new Error('Network error')));

            xhr.open('POST', this.apiEndpoint);
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.send(JSON.stringify({ imageBase64: base64 }));
        });
    }

    fileToBase64(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => resolve(reader.result.split(',')[1]);
            reader.onerror = reject;
            reader.readAsDataURL(file);
        });
    }
}

// Usage example
const scanner = new BarcodeScanner();

// Initialize camera scanning
document.getElementById('startCamera').addEventListener('click', async () => {
    const initialized = await scanner.initializeCamera('videoPreview');
    if (initialized) {
        // Start continuous scanning
        setInterval(async () => {
            try {
                const result = await scanner.captureAndScan();
                if (result.barcodes.length > 0) {
                    console.log('Barcodes detected:', result.barcodes);
                    // Process results
                }
            } catch (error) {
                console.error('Scan error:', error);
            }
        }, 1000); // Scan every second
    }
});
// Modern JavaScript client with camera support
class BarcodeScanner {
    constructor(apiEndpoint = '/api/barcode/scan') {
        this.apiEndpoint = apiEndpoint;
        this.videoElement = null;
        this.canvasElement = null;
    }

    // Initialize camera for live capture
    async initializeCamera(videoElementId) {
        this.videoElement = document.getElementById(videoElementId);

        try {
            const stream = await navigator.mediaDevices.getUserMedia({
                video: { 
                    facingMode: 'environment', // Use rear camera on mobile
                    width: { ideal: 1280 },
                    height: { ideal: 720 }
                }
            });
            this.videoElement.srcObject = stream;

            // Create canvas for capturing frames
            this.canvasElement = document.createElement('canvas');
            this.canvasElement.width = 1280;
            this.canvasElement.height = 720;

            return true;
        } catch (error) {
            console.error('Camera initialization failed:', error);
            return false;
        }
    }

    // Capture frame and scan
    async captureAndScan() {
        if (!this.videoElement || !this.canvasElement) {
            throw new Error('Camera not initialized');
        }

        const context = this.canvasElement.getContext('2d');
        context.drawImage(this.videoElement, 0, 0, 
                         this.canvasElement.width, 
                         this.canvasElement.height);

        // Convert to base64
        const imageData = this.canvasElement.toDataURL('image/jpeg', 0.8);
        const base64 = imageData.split(',')[1];

        // Send to API
        const response = await fetch(this.apiEndpoint, {
            method: 'POST',
            headers: { 
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest' // CSRF protection
            },
            body: JSON.stringify({ 
                imageBase64: base64,
                expectMultiple: true 
            })
        });

        if (!response.ok) {
            throw new Error(`API error: ${response.statusText}`);
        }

        return await response.json();
    }

    // Scan from file upload with progress
    async scanFile(file, progressCallback) {
        const base64 = await this.fileToBase64(file);

        const xhr = new XMLHttpRequest();

        return new Promise((resolve, reject) => {
            xhr.upload.addEventListener('progress', (e) => {
                if (progressCallback && e.lengthComputable) {
                    progressCallback(Math.round((e.loaded / e.total) * 100));
                }
            });

            xhr.addEventListener('load', () => {
                if (xhr.status === 200) {
                    resolve(JSON.parse(xhr.responseText));
                } else {
                    reject(new Error(`Server error: ${xhr.status}`));
                }
            });

            xhr.addEventListener('error', () => reject(new Error('Network error')));

            xhr.open('POST', this.apiEndpoint);
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.send(JSON.stringify({ imageBase64: base64 }));
        });
    }

    fileToBase64(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => resolve(reader.result.split(',')[1]);
            reader.onerror = reject;
            reader.readAsDataURL(file);
        });
    }
}

// Usage example
const scanner = new BarcodeScanner();

// Initialize camera scanning
document.getElementById('startCamera').addEventListener('click', async () => {
    const initialized = await scanner.initializeCamera('videoPreview');
    if (initialized) {
        // Start continuous scanning
        setInterval(async () => {
            try {
                const result = await scanner.captureAndScan();
                if (result.barcodes.length > 0) {
                    console.log('Barcodes detected:', result.barcodes);
                    // Process results
                }
            } catch (error) {
                console.error('Scan error:', error);
            }
        }, 1000); // Scan every second
    }
});
' Modern JavaScript client with camera support
Public Class BarcodeScanner
    Private apiEndpoint As String
    Private videoElement As Object
    Private canvasElement As Object

    Public Sub New(Optional apiEndpoint As String = "/api/barcode/scan")
        Me.apiEndpoint = apiEndpoint
        Me.videoElement = Nothing
        Me.canvasElement = Nothing
    End Sub

    ' Initialize camera for live capture
    Public Async Function InitializeCamera(videoElementId As String) As Task(Of Boolean)
        Me.videoElement = document.getElementById(videoElementId)

        Try
            Dim stream = Await navigator.mediaDevices.getUserMedia(New With {
                .video = New With {
                    .facingMode = "environment", ' Use rear camera on mobile
                    .width = New With {.ideal = 1280},
                    .height = New With {.ideal = 720}
                }
            })
            Me.videoElement.srcObject = stream

            ' Create canvas for capturing frames
            Me.canvasElement = document.createElement("canvas")
            Me.canvasElement.width = 1280
            Me.canvasElement.height = 720

            Return True
        Catch ex As Exception
            console.error("Camera initialization failed:", ex)
            Return False
        End Try
    End Function

    ' Capture frame and scan
    Public Async Function CaptureAndScan() As Task(Of Object)
        If Me.videoElement Is Nothing OrElse Me.canvasElement Is Nothing Then
            Throw New Exception("Camera not initialized")
        End If

        Dim context = Me.canvasElement.getContext("2d")
        context.drawImage(Me.videoElement, 0, 0, Me.canvasElement.width, Me.canvasElement.height)

        ' Convert to base64
        Dim imageData = Me.canvasElement.toDataURL("image/jpeg", 0.8)
        Dim base64 = imageData.Split(","c)(1)

        ' Send to API
        Dim response = Await fetch(Me.apiEndpoint, New With {
            .method = "POST",
            .headers = New With {
                .ContentType = "application/json",
                .XRequestedWith = "XMLHttpRequest" ' CSRF protection
            },
            .body = JSON.stringify(New With {
                .imageBase64 = base64,
                .expectMultiple = True
            })
        })

        If Not response.ok Then
            Throw New Exception($"API error: {response.statusText}")
        End If

        Return Await response.json()
    End Function

    ' Scan from file upload with progress
    Public Async Function ScanFile(file As Object, progressCallback As Action(Of Integer)) As Task(Of Object)
        Dim base64 = Await Me.FileToBase64(file)

        Dim xhr = New XMLHttpRequest()

        Return Await Task.Run(Function()
                                  Dim tcs = New TaskCompletionSource(Of Object)()

                                  AddHandler xhr.upload.progress, Sub(e)
                                                                      If progressCallback IsNot Nothing AndAlso e.lengthComputable Then
                                                                          progressCallback(Math.Round((e.loaded / e.total) * 100))
                                                                      End If
                                                                  End Sub

                                  AddHandler xhr.load, Sub()
                                                           If xhr.status = 200 Then
                                                               tcs.SetResult(JSON.parse(xhr.responseText))
                                                           Else
                                                               tcs.SetException(New Exception($"Server error: {xhr.status}"))
                                                           End If
                                                       End Sub

                                  AddHandler xhr.error, Sub() tcs.SetException(New Exception("Network error"))

                                  xhr.open("POST", Me.apiEndpoint)
                                  xhr.setRequestHeader("Content-Type", "application/json")
                                  xhr.send(JSON.stringify(New With {.imageBase64 = base64}))

                                  Return tcs.Task
                              End Function)
    End Function

    Private Function FileToBase64(file As Object) As Task(Of String)
        Return Task.Run(Function()
                            Dim tcs = New TaskCompletionSource(Of String)()
                            Dim reader = New FileReader()

                            AddHandler reader.onload, Sub() tcs.SetResult(reader.result.Split(","c)(1))
                            AddHandler reader.onerror, Sub() tcs.SetException(New Exception("File read error"))

                            reader.readAsDataURL(file)

                            Return tcs.Task
                        End Function)
    End Function
End Class

' Usage example
Dim scanner = New BarcodeScanner()

' Initialize camera scanning
document.getElementById("startCamera").addEventListener("click", Async Sub()
    Dim initialized = Await scanner.InitializeCamera("videoPreview")
    If initialized Then
        ' Start continuous scanning
        setInterval(Async Sub()
                        Try
                            Dim result = Await scanner.CaptureAndScan()
                            If result.barcodes.length > 0 Then
                                console.log("Barcodes detected:", result.barcodes)
                                ' Process results
                            End If
                        Catch ex As Exception
                            console.error("Scan error:", ex)
                        End Try
                    End Sub, 1000) ' Scan every second
    End If
End Sub)
$vbLabelText   $csharpLabel

這種 API 方法可以與現代 JavaScript 框架和行動應用程式無縫整合。 對於行動端特定實現,請探索iOSAndroid部署選項,以及.NET MAUI 條碼掃描。 其他功能包括將條碼匯出為 HTML以及從資料來源建立條碼。 對於條碼產生需求,請探索建立 1-BPP 條碼圖像編寫 Unicode 條碼

API 如何處理多個條碼?

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

IronBarcode 可以有效地處理單張影像中的多個條碼,並傳回每個偵測到的條碼的詳細信息,包括位置資料和置信度分數。

JSON回應結構是什麼樣的?

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

結構化的 JSON 回應包含客戶端應用程式有效處理和顯示條碼結果所需的所有元資料。 ## 如何處理複雜的條碼影像?

現實世界中的條碼掃描經常會遇到影像不完美的情況:例如拍攝角度不當、光線不足或條碼部分損壞等。 IronBarcode憑藉其先進的影像處理能力機器學習置信度閾值,在這些場景中表現出色。 圖書館的容錯功能確保即使在不利條件下也能可靠地讀取資料。 針對具體挑戰,探索條碼無法辨識問題MSI 條碼辨識問題的解決方案。 該庫還可以透過影像校正來處理不完美的條碼

您應該為哪些常見的故障排除場景做好準備?

生產條碼掃描應用會遇到各種挑戰,需要採用系統性的故障排除方法。 誤報故障排除指南有助於提高偵測準確度:

模糊或低品質影像

  • 使用影像校正濾鏡套用銳利化濾鏡
  • 使用對比度調整功能改善褪色的條碼。
  • 考慮使用不同的設定進行多次處理

旋轉或傾斜的條碼

  • 啟用AutoRotate以自動校正方向
  • 如有需要,處理多個旋轉角度的影像
  • 對嚴重傾斜的影像使用透視校正

條碼損壞或不完整

誤報檢測

  • 設定合適的置信閾值
  • 根據預期模式驗證條碼格式
  • 與已知的條碼資料庫進行交叉比對

效能問題

如何實現高階影像處理?

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

    public async Task<List<BarcodeResult>> ProcessChallengingImage(
        Stream imageStream, 
        BarcodeProcessingProfile profile = BarcodeProcessingProfile.Balanced)
    {
        var options = GetOptionsForProfile(profile);

        // First pass: Try with standard settings
        var results = BarcodeReader.Read(imageStream, options);

        if (!results.Any() && profile == BarcodeProcessingProfile.Aggressive)
        {
            // Second pass: Apply aggressive image corrections
            imageStream.Position = 0;
            options.ImageFilters = new ImageFilterCollection
            {
                new SharpenFilter(2.5f),
                new ContrastFilter(2.0f),
                new BrightnessFilter(1.2f),
                new InvertFilter() // Try inverted colors
            };
            options.AutoRotate = true;
            options.Speed = ReadingSpeed.ExtremeDetail;

            results = BarcodeReader.Read(imageStream, options);
        }

        return results.Select(r => new BarcodeResult
        {
            Value = r.Text,
            Type = r.BarcodeType,
            Confidence = r.Confidence,
            Metadata = ExtractMetadata(r)
        }).ToList();
    }

    private BarcodeReaderOptions GetOptionsForProfile(BarcodeProcessingProfile profile)
    {
        return profile switch
        {
            BarcodeProcessingProfile.Fast => new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Faster,
                ExpectMultipleBarcodes = false,
                UseConfidenceThreshold = false,
                Multithreaded = false
            },
            BarcodeProcessingProfile.Balanced => new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Balanced,
                ExpectBarcodeTypes = BarcodeEncoding.QRCode | 
                                    BarcodeEncoding.Code128 | 
                                    BarcodeEncoding.Code39,
                AutoRotate = true,
                ImageFilters = new ImageFilterCollection
                {
                    new SharpenFilter(),
                    new ContrastFilter(1.5f)
                },
                Multithreaded = true,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.75
            },
            BarcodeProcessingProfile.Aggressive => new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Detailed,
                ExpectMultipleBarcodes = true,
                AutoRotate = true,
                RemoveFalsePositive = true,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.6,
                Multithreaded = true,
                // Try multiple barcode types
                ExpectBarcodeTypes = BarcodeEncoding.All
            },
            _ => throw new ArgumentException($"Unknown profile: {profile}")
        };
    }

    private Dictionary<string, object> ExtractMetadata(BarcodeResult result)
    {
        return new Dictionary<string, object>
        {
            ["Width"] = result.Width,
            ["Height"] = result.Height,
            ["RotationAngle"] = result.RotationAngle,
            ["PageNumber"] = result.PageNumber,
            ["Confidence"] = result.Confidence
        };
    }
}

public enum BarcodeProcessingProfile
{
    Fast,      // For real-time scanning
    Balanced,  // Default for most scenarios  
    Aggressive // For challenging images
}
public class AdvancedBarcodeProcessor
{
    private readonly ILogger<AdvancedBarcodeProcessor> _logger;

    public async Task<List<BarcodeResult>> ProcessChallengingImage(
        Stream imageStream, 
        BarcodeProcessingProfile profile = BarcodeProcessingProfile.Balanced)
    {
        var options = GetOptionsForProfile(profile);

        // First pass: Try with standard settings
        var results = BarcodeReader.Read(imageStream, options);

        if (!results.Any() && profile == BarcodeProcessingProfile.Aggressive)
        {
            // Second pass: Apply aggressive image corrections
            imageStream.Position = 0;
            options.ImageFilters = new ImageFilterCollection
            {
                new SharpenFilter(2.5f),
                new ContrastFilter(2.0f),
                new BrightnessFilter(1.2f),
                new InvertFilter() // Try inverted colors
            };
            options.AutoRotate = true;
            options.Speed = ReadingSpeed.ExtremeDetail;

            results = BarcodeReader.Read(imageStream, options);
        }

        return results.Select(r => new BarcodeResult
        {
            Value = r.Text,
            Type = r.BarcodeType,
            Confidence = r.Confidence,
            Metadata = ExtractMetadata(r)
        }).ToList();
    }

    private BarcodeReaderOptions GetOptionsForProfile(BarcodeProcessingProfile profile)
    {
        return profile switch
        {
            BarcodeProcessingProfile.Fast => new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Faster,
                ExpectMultipleBarcodes = false,
                UseConfidenceThreshold = false,
                Multithreaded = false
            },
            BarcodeProcessingProfile.Balanced => new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Balanced,
                ExpectBarcodeTypes = BarcodeEncoding.QRCode | 
                                    BarcodeEncoding.Code128 | 
                                    BarcodeEncoding.Code39,
                AutoRotate = true,
                ImageFilters = new ImageFilterCollection
                {
                    new SharpenFilter(),
                    new ContrastFilter(1.5f)
                },
                Multithreaded = true,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.75
            },
            BarcodeProcessingProfile.Aggressive => new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Detailed,
                ExpectMultipleBarcodes = true,
                AutoRotate = true,
                RemoveFalsePositive = true,
                UseConfidenceThreshold = true,
                ConfidenceThreshold = 0.6,
                Multithreaded = true,
                // Try multiple barcode types
                ExpectBarcodeTypes = BarcodeEncoding.All
            },
            _ => throw new ArgumentException($"Unknown profile: {profile}")
        };
    }

    private Dictionary<string, object> ExtractMetadata(BarcodeResult result)
    {
        return new Dictionary<string, object>
        {
            ["Width"] = result.Width,
            ["Height"] = result.Height,
            ["RotationAngle"] = result.RotationAngle,
            ["PageNumber"] = result.PageNumber,
            ["Confidence"] = result.Confidence
        };
    }
}

public enum BarcodeProcessingProfile
{
    Fast,      // For real-time scanning
    Balanced,  // Default for most scenarios  
    Aggressive // For challenging images
}
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Threading.Tasks

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

    Public Async Function ProcessChallengingImage(imageStream As Stream, Optional profile As BarcodeProcessingProfile = BarcodeProcessingProfile.Balanced) As Task(Of List(Of BarcodeResult))
        Dim options = GetOptionsForProfile(profile)

        ' First pass: Try with standard settings
        Dim results = BarcodeReader.Read(imageStream, options)

        If Not results.Any() AndAlso profile = BarcodeProcessingProfile.Aggressive Then
            ' Second pass: Apply aggressive image corrections
            imageStream.Position = 0
            options.ImageFilters = New ImageFilterCollection From {
                New SharpenFilter(2.5F),
                New ContrastFilter(2.0F),
                New BrightnessFilter(1.2F),
                New InvertFilter() ' Try inverted colors
            }
            options.AutoRotate = True
            options.Speed = ReadingSpeed.ExtremeDetail

            results = BarcodeReader.Read(imageStream, options)
        End If

        Return results.Select(Function(r) New BarcodeResult With {
            .Value = r.Text,
            .Type = r.BarcodeType,
            .Confidence = r.Confidence,
            .Metadata = ExtractMetadata(r)
        }).ToList()
    End Function

    Private Function GetOptionsForProfile(profile As BarcodeProcessingProfile) As BarcodeReaderOptions
        Select Case profile
            Case BarcodeProcessingProfile.Fast
                Return New BarcodeReaderOptions With {
                    .Speed = ReadingSpeed.Faster,
                    .ExpectMultipleBarcodes = False,
                    .UseConfidenceThreshold = False,
                    .Multithreaded = False
                }
            Case BarcodeProcessingProfile.Balanced
                Return New BarcodeReaderOptions With {
                    .Speed = ReadingSpeed.Balanced,
                    .ExpectBarcodeTypes = BarcodeEncoding.QRCode Or BarcodeEncoding.Code128 Or BarcodeEncoding.Code39,
                    .AutoRotate = True,
                    .ImageFilters = New ImageFilterCollection From {
                        New SharpenFilter(),
                        New ContrastFilter(1.5F)
                    },
                    .Multithreaded = True,
                    .UseConfidenceThreshold = True,
                    .ConfidenceThreshold = 0.75
                }
            Case BarcodeProcessingProfile.Aggressive
                Return New BarcodeReaderOptions With {
                    .Speed = ReadingSpeed.Detailed,
                    .ExpectMultipleBarcodes = True,
                    .AutoRotate = True,
                    .RemoveFalsePositive = True,
                    .UseConfidenceThreshold = True,
                    .ConfidenceThreshold = 0.6,
                    .Multithreaded = True,
                    .ExpectBarcodeTypes = BarcodeEncoding.All
                }
            Case Else
                Throw New ArgumentException($"Unknown profile: {profile}")
        End Select
    End Function

    Private Function ExtractMetadata(result As BarcodeResult) As Dictionary(Of String, Object)
        Return New Dictionary(Of String, Object) From {
            {"Width", result.Width},
            {"Height", result.Height},
            {"RotationAngle", result.RotationAngle},
            {"PageNumber", result.PageNumber},
            {"Confidence", result.Confidence}
        }
    End Function
End Class

Public Enum BarcodeProcessingProfile
    Fast      ' For real-time scanning
    Balanced  ' Default for most scenarios  
    Aggressive ' For challenging images
End Enum
$vbLabelText   $csharpLabel

BarcodeReaderOptions類別提供了對掃描的精細控制。 AutoRotate功能可以處理以任何角度拍攝的影像,而影像濾鏡可以提高模糊或低對比度條碼的清晰度。 Speed 屬性可根據您的應用程式需求,在處理速度和準確性之間取得平衡。 如需詳細配置,請參閱條碼閱讀器設定範例PDF 特定閱讀器設定。 使用 PDF 檔案時,可以考慮在 PDF 文件上新增條碼,或將條碼建立為 PDF 文件。 對於大批量處理,啟用多執行緒可以顯著提高效能。 這種方法符合影像處理產業的最佳實踐。 針對特定場景,探索不完善的條碼校正作物區域規範。 圖書館的條碼讀取教程提供了有關高級配置的更多見解。

如何實現瀏覽器相容性和回退策略?

支援多種瀏覽器需要實現漸進增強。 考慮使用System.Drawing 相容性進行跨平台影像處理。 該庫的Blazor 整合以最少的配置提供現代 Web 應用程式支援。 部署問題,請參閱執行時期複製異常指南

@* Razor view with progressive enhancement *@
<div class="barcode-scanner-container">
    @* Modern camera capture for supported browsers *@
    <div id="cameraSection" class="d-none">
        <video id="videoPreview" class="w-100" autoplay></video>
        <button id="captureBtn" class="btn btn-primary mt-2">
            Capture & Scan
        </button>
    </div>

    @* Fallback file upload for all browsers *@
    <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 & Scan
            </button>
        </form>
    </div>
</div>

<script>
// Feature detection and progressive enhancement
(function() {
    const hasMediaDevices = 'mediaDevices' in navigator;
    const hasGetUserMedia = hasMediaDevices && 
                           'getUserMedia' in navigator.mediaDevices;

    if (hasGetUserMedia) {
        // Show camera section for modern browsers
        document.getElementById('cameraSection').classList.remove('d-none');

        // Optional: Hide upload section or make it secondary
        const uploadSection = document.getElementById('uploadSection');
        uploadSection.innerHTML = '<p class="text-muted">Or upload a file:</p>' + 
                                 uploadSection.innerHTML;
    }

    // Browser-specific optimizations
    const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
    const isAndroid = /Android/.test(navigator.userAgent);

    if (isIOS) {
        // iOS-specific handling
        document.querySelector('input[type="file"]')
                .setAttribute('accept', 'image/*');
    }
})();
</script>
@* Razor view with progressive enhancement *@
<div class="barcode-scanner-container">
    @* Modern camera capture for supported browsers *@
    <div id="cameraSection" class="d-none">
        <video id="videoPreview" class="w-100" autoplay></video>
        <button id="captureBtn" class="btn btn-primary mt-2">
            Capture & Scan
        </button>
    </div>

    @* Fallback file upload for all browsers *@
    <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 & Scan
            </button>
        </form>
    </div>
</div>

<script>
// Feature detection and progressive enhancement
(function() {
    const hasMediaDevices = 'mediaDevices' in navigator;
    const hasGetUserMedia = hasMediaDevices && 
                           'getUserMedia' in navigator.mediaDevices;

    if (hasGetUserMedia) {
        // Show camera section for modern browsers
        document.getElementById('cameraSection').classList.remove('d-none');

        // Optional: Hide upload section or make it secondary
        const uploadSection = document.getElementById('uploadSection');
        uploadSection.innerHTML = '<p class="text-muted">Or upload a file:</p>' + 
                                 uploadSection.innerHTML;
    }

    // Browser-specific optimizations
    const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
    const isAndroid = /Android/.test(navigator.userAgent);

    if (isIOS) {
        // iOS-specific handling
        document.querySelector('input[type="file"]')
                .setAttribute('accept', 'image/*');
    }
})();
</script>
@* Razor view with progressive enhancement *@
<div class="barcode-scanner-container">
    @* Modern camera capture for supported browsers *@
    <div id="cameraSection" class="d-none">
        <video id="videoPreview" class="w-100" autoplay></video>
        <button id="captureBtn" class="btn btn-primary mt-2">
            Capture & Scan
        </button>
    </div>

    @* Fallback file upload for all browsers *@
    <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 & Scan
            </button>
        </form>
    </div>
</div>

<script>
' Feature detection and progressive enhancement
(function()
    Dim hasMediaDevices As Boolean = "mediaDevices" In navigator
    Dim hasGetUserMedia As Boolean = hasMediaDevices AndAlso 
                                     "getUserMedia" In navigator.mediaDevices

    If hasGetUserMedia Then
        ' Show camera section for modern browsers
        document.getElementById("cameraSection").classList.remove("d-none")

        ' Optional: Hide upload section or make it secondary
        Dim uploadSection = document.getElementById("uploadSection")
        uploadSection.innerHTML = "<p class='text-muted'>Or upload a file:</p>" & 
                                  uploadSection.innerHTML
    End If

    ' Browser-specific optimizations
    Dim isIOS As Boolean = /iPad|iPhone|iPod/.test(navigator.userAgent)
    Dim isAndroid As Boolean = /Android/.test(navigator.userAgent)

    If isIOS Then
        ' iOS-specific handling
        document.querySelector("input[type='file']")
                .setAttribute("accept", "image/*")
    End If
End Function)()
</script>
$vbLabelText   $csharpLabel

生產條碼掃描的最佳實踐是什麼?

在 ASP.NET Web 應用程式中使用 IronBarcode 實作條碼掃描,可以將複雜的任務轉換為簡單易維護的程式碼。 該庫能夠處理多種格式、處理不完美的圖像、解碼條碼,並在各個平台上提供一致的結果,這使得它對於企業應用程式來說非常寶貴。 使用特殊格式時,請查閱有關建立一維條碼建立二維條碼編寫 Unicode 條碼的指南。 該庫的產品更新體現了持續的改進,包括支援新格式和高級功能,如MicroQR 和 rMQR

您應該遵循哪些安全最佳實務?

生產條碼掃描系統必須實施全面的安全措施,以抵禦各種攻擊途徑。 請查閱IronBarcode 安全 CVE以取得最新的安全性更新:

資料驗證與清理

  • 處理前驗證所有條碼內容
  • 對預期格式實施白名單驗證
  • 在將資料儲存到資料庫之前進行清理。
  • 防止透過參數化查詢進行 SQL 注入

存取控制和身份驗證

  • 實施基於角色的存取控制(RBAC)
  • 使用安全的身份驗證機制
  • 記錄所有條碼掃描活動
  • 監控異常掃描模式 正確應用許可證密鑰

安全通訊

  • 對所有 API 端點強制使用 HTTPS
  • 為行動應用實現憑證綁定
  • 使用安全的WebSocket連線進行即時掃描
  • 對傳輸中和靜態的敏感條碼資料進行加密

哪些效能優化技術適用?

對於生產環境部署,請考慮以下架構建議,以最大限度地提高效能和可靠性:

實現請求限流: 使用滑動視窗演算法進行速率限制,防止 API 被濫用,實現公平使用。 實施以客戶分配配額制,以確保資源公平分配。

策略性地使用快取: 使用分散式快取來快取重複掃描的條碼結果,以實現規模化。 設定合適的 TTL 值並使用匯出到串流功能以提高記憶體效率。

監控效能指標: 追蹤每種條碼類型的處理時間,並使用置信度閾值監控成功率/失敗率。 發出效能下降警報並分析輸出資料格式,以尋找最佳化機會。

為了提高安全性,請驗證上傳的文件,實施正確的許可證金鑰管理,包括web.config 配置正確應用許可證金鑰,並考慮對大文件使用串流方法。 IronBarcode 的安全措施透過DigiCert 認證和防篡改功能確保安全運作。 該程式庫的跨平台支援確保您的解決方案能夠在Docker 容器和雲端環境中無縫運行。 有關部署打包,請參閱MSI 安裝程序指南故障排除缺失 DLL

準備好利用專業的條碼掃描功能徹底革新您的 ASP.NET 應用程式了嗎? 瀏覽完整的API 文檔,了解批次處理PDF 條碼提取在 PDF 上添加條碼以及自訂樣式選項等高級功能。 有關二維碼的特定功能,請探索二維碼樣式糾錯設定。 其他輸出選項包括建立條碼為 PDF影像1-BPP 影像,以及設定條碼邊距。 立即開始免費試用,探索 IronBarcode 在生產環境中的全部潛力。

常見問題解答

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

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

IronBarcode 如何在 ASP.NET 中實現條碼掃描?

IronBarcode 透過提供可靠且高效的元件簡化了 ASP.NET 中的條碼掃描流程,這些元件可以輕鬆整合到 Web 應用程式中,使開發人員能夠快速實現掃描功能。

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

IronBarcode 支援掃描各種條碼格式,包括傳統的線性條碼和現代的二維條碼,確保與各種應用程式相容。

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

是的,IronBarcode 非常適合文件處理工作流程,它可以透過掃描嵌入式條碼來數位化和整理紙本文件。

IronBarcode 是否適用於庫存管理系統?

IronBarcode 是庫存管理系統的絕佳選擇,因為它能夠透過掃描條碼有效地追蹤產品,從而簡化操作並最大限度地減少錯誤。

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

透過整合 IronBarcode,活動門票處理變得無縫銜接,因為它能夠快速掃描門票條碼,從而促進活動現場快速、準確地進行入場管理。

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

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

IronBarcode 的實作是否需要大量的程式設計知識?

不,IronBarcode 的設計對開發者非常友好,即使編碼知識有限,也能輕鬆地在 ASP.NET 應用程式中實現條碼掃描功能。

IronBarcode可以用於行動網路應用程式嗎?

是的,IronBarcode 可以整合到行動 Web 應用程式中,從而實現隨時隨地掃描條碼,並增強 ASP.NET 專案的多功能性。

Curtis Chau
技術撰稿人

Curtis Chau 擁有電腦科學學士學位(卡爾頓大學),專長於前端開發,精通 Node.js、TypeScript、JavaScript 和 React。Curtis 對製作直覺且美觀的使用者介面充滿熱情,他喜歡使用現代化的架構,並製作結構良好且視覺上吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 也有濃厚的興趣,他喜歡探索整合硬體與軟體的創新方式。在空閒時間,他喜歡玩遊戲和建立 Discord bots,將他對技術的熱愛與創意結合。