跳至頁尾內容
影片

如何在 C# 中從 PDF 讀取條碼

從BarcodeScanning.Native.Maui 遷移到IronBarcode

本指南提供從BarcodeScanning.Native.Maui 到IronBarcode 的完整遷移路徑,涵蓋相機事件模式替換、命名空間變更、程式碼遷移範例,以及BarcodeScanning.Native.Maui 無法解決的場景處理——Windows MAUI、文件和PDF 輸入、伺服器端處理和條碼生成。

為什麼要從BarcodeScanning.MAUI 遷移

從BarcodeScanning.Native.Maui 遷移的團隊報告如下觸發因素:

需要Windows MAUI 目標: BarcodeScanning.Native.Maui 封裝iOS 和Android 本機API。它沒有Windows 實現,也沒有計畫。 如果您的MAUI 應用程式同時以Windows、iOS 和Android 為目標,您需要一個在所有三個目標上都能運行而無需平台特定分支的庫。

文件或PDF 輸入新增到需求中: BarcodeScanning.Native.Maui 只接受即時相機幀。 當使用者需要從他們的資料庫中上傳圖像,或當伺服器端端點需要從PDF 中提取條碼時,該庫沒有程式碼路徑可供提供。 任何文件或PDF 條碼場景都需要不同的工具。

iOS UPC-A 資料在生產中是錯誤的:蘋果的Vision 框架返回13 個位元的UPC-A 條碼(EAN-13 編碼)。 BarcodeScanning.Native.Maui 將此資訊未經校正地傳遞過去。 如果UPC-A 程式碼以領先零儲存,庫存記錄、銷售點查找或供應鏈整合可能已經在不知不覺中被破壞。IronBarcode返回正確的12 位UPC-A 值,無需手動校正。

PDF417 掃描不可靠:該庫自己的GitHub 問題記錄PDF417 為"非常有問題——大多數掃描從未發生過"。對於運送標籤、駕駛執照和登機證,這是直接的阻礙。

需要生成: BarcodeScanning.Native.Maui 無法生成條碼。IronBarcode生成Code128、QR、DataMatrix 和其他格式作為圖像文件或字節陣列。

引入了伺服器端處理: BarcodeScanning.Native.Maui 是相機UI 控制——它無法在伺服器進程中運行。 當需要伺服器端條碼閱讀時,與移動掃描相結合,IronBarcode 使用相同的包和相同的API 覆蓋兩方面。

基本問題

BarcodeScanning.Native.Maui 完全將您的條碼閱讀綁定到現場相機事件模式。 任何需求一旦超出該模式,該庫將一無所提供:

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode != null)
        ResultLabel.Text = barcode.DisplayValue;
}
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode != null)
        ResultLabel.Text = barcode.DisplayValue;
}
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
    Dim barcode = e.BarcodeResults.FirstOrDefault()
    If barcode IsNot Nothing Then
        ResultLabel.Text = barcode.DisplayValue
    End If
End Sub
$vbLabelText   $csharpLabel

IronBarcode 接受任何資料輸入——相機捕捉、文件、PDF、字節陣列——並可在每個平臺運行:

using IronBarCode;

private async void ScanBarcodeButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    ResultLabel.Text = results.FirstOrDefault()?.Value ?? "No barcode found";
}
using IronBarCode;

private async void ScanBarcodeButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    ResultLabel.Text = results.FirstOrDefault()?.Value ?? "No barcode found";
}
Imports IronBarCode

Private Async Sub ScanBarcodeButton_Clicked(sender As Object, e As EventArgs)
    Dim photo = Await MediaPicker.CapturePhotoAsync()
    If photo Is Nothing Then Return

    Using stream = Await photo.OpenReadAsync()
        Using ms As New MemoryStream()
            Await stream.CopyToAsync(ms)

            Dim results = BarcodeReader.Read(ms.ToArray())
            ResultLabel.Text = If(results.FirstOrDefault()?.Value, "No barcode found")
        End Using
    End Using
End Sub
$vbLabelText   $csharpLabel

IronBarcodevs BarcodeScanning.MAUI:功能比較

功能 BarcodeScanning.MAUI IronBarcode
即時相機幀閱讀 是——CameraView 控制 否(使用MediaPicker 捕獲,然後閱讀)
應用程式内相機取景器 是——實時連續 否——通過MediaPicker 使用系統相機UI
從圖像文件中閱讀 是——BarcodeReader.Read(path)
從字節陣列中閱讀 是——BarcodeReader.Read(bytes)
從流中閱讀 是——BarcodeReader.Read(stream)
從PDF 中閱讀 是——BarcodeReader.Read(pdf)
條碼生成 是——BarcodeWriter + QRCodeWriter
Windows MAUI 支持
iOS MAUI 支持
Android MAUI 支持
macOS MAUI 支持 未記錄
伺服器端 / ASP.NET
Docker / Azure / AWS Lambda
iOS UPC-A 準確度 返還13 位數字(錯誤),需要手動校正 返回正確的12 位UPC-A
PDF417 可靠性 "大多數掃描從未發生"(GitHub 問題) 支持
多條碼檢測 是(使用每個幀的多個 e.BarcodeResults ) 是(ExpectMultipleBarcodes 選項)
閱讀速度控制 None ReadingSpeed.Faster / Balanced / Detailed / ExtremeDetail
許可證 MIT(開源,免費) 商業——Lite $749,Plus $1,499,Professional $2,999,Unlimited $5,999
.NET Framework支持 否(僅限MAUI) 是—.NET Framework 4.6.2+

快速入門:BarcodeScanning.MAUI 到IronBarcode 遷移

步驟 1:替換 NuGet 包

移除BarcodeScanning.Native.Maui:

dotnet remove package BarcodeScanning.Native.Maui
dotnet remove package BarcodeScanning.Native.Maui
SHELL

安裝IronBarcode:

dotnet add package IronBarcode
dotnet add package IronBarcode
SHELL

步驟 2:更新命名空間

從所有文件中移除BarcodeScanning 命名空間:

// Remove
using BarcodeScanning;
// Remove
using BarcodeScanning;
Imports BarcodeScanning
$vbLabelText   $csharpLabel

新增 IronBarCode 命名空間:

// Add
using IronBarCode;
// Add
using IronBarCode;
Imports IronBarCode
$vbLabelText   $csharpLabel

在XAML 文件中,移除scanner: XML 命名空間宣告:


xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui"

xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui"
XML

步驟 3:初始化授權

在應用程式啟動時新增許可初始化——在MauiProgram.csApp.xaml.cs 中:

IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode

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

程式碼遷移範例

相機掃描:從CameraView 到MediaPicker

CameraView 控件提供了一個實時取景器,具有連續幀檢測。IronBarcode替換使用MAUI 的MediaPicker 開啟系統相機,拍攝照片並處理所得到的圖像。

BarcodeScanning.MAUI 方法——XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui">
    <StackLayout>
        <scanner:CameraView x:Name="CameraView"
                            OnDetectionFinished="OnBarcodeDetected"
                            CameraEnabled="True"
                            BarcodeFormats="All"
                            VerticalOptions="FillAndExpand" />
        <Label x:Name="ResultLabel" Text="Waiting for scan..." />
    </StackLayout>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui">
    <StackLayout>
        <scanner:CameraView x:Name="CameraView"
                            OnDetectionFinished="OnBarcodeDetected"
                            CameraEnabled="True"
                            BarcodeFormats="All"
                            VerticalOptions="FillAndExpand" />
        <Label x:Name="ResultLabel" Text="Waiting for scan..." />
    </StackLayout>
</ContentPage>
XML

BarcodeScanning.MAUI 方法——後端程式碼:

using BarcodeScanning;

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode != null)
        MainThread.BeginInvokeOnMainThread(() =>
            ResultLabel.Text = barcode.DisplayValue);
}
using BarcodeScanning;

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode != null)
        MainThread.BeginInvokeOnMainThread(() =>
            ResultLabel.Text = barcode.DisplayValue);
}
Imports BarcodeScanning

Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
    Dim barcode = e.BarcodeResults.FirstOrDefault()
    If barcode IsNot Nothing Then
        MainThread.BeginInvokeOnMainThread(Sub()
                                               ResultLabel.Text = barcode.DisplayValue
                                           End Sub)
    End If
End Sub
$vbLabelText   $csharpLabel

IronBarcode方法——XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
    <StackLayout>
        <Button Text="Scan Barcode" Clicked="ScanButton_Clicked" />
        <Label x:Name="ResultLabel" Text="Tap to scan..." />
    </StackLayout>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
    <StackLayout>
        <Button Text="Scan Barcode" Clicked="ScanButton_Clicked" />
        <Label x:Name="ResultLabel" Text="Tap to scan..." />
    </StackLayout>
</ContentPage>
XML

IronBarcode方法——後端程式碼:

using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var first = results.FirstOrDefault();
    ResultLabel.Text = first?.Value ?? "No barcode found";
}
using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var first = results.FirstOrDefault();
    ResultLabel.Text = first?.Value ?? "No barcode found";
}
Imports IronBarCode
Imports System.IO
Imports System.Linq

Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
    Dim photo = Await MediaPicker.CapturePhotoAsync()
    If photo Is Nothing Then Return

    Using stream = Await photo.OpenReadAsync()
        Using ms As New MemoryStream()
            Await stream.CopyToAsync(ms)

            Dim results = BarcodeReader.Read(ms.ToArray())
            Dim first = results.FirstOrDefault()
            ResultLabel.Text = If(first?.Value, "No barcode found")
        End Using
    End Using
End Sub
$vbLabelText   $csharpLabel

此程式碼可在iOS、Android 和Windows MAUI 上運行,而無需任何平台特定的分支。 使用者體驗從一個現場應用程式取景器轉變為平台的本機相機螢幕——適合大多數商業應用。 IronBarcode MAUI 閱讀指南 涵蓋了更多配置選項。

處理每次掃描的多個條碼

BarcodeScanning.MAUI 方法:

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    foreach (var barcode in e.BarcodeResults)
    {
        MainThread.BeginInvokeOnMainThread(() =>
            Console.WriteLine($"Found: {barcode.DisplayValue}"));
    }
}
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    foreach (var barcode in e.BarcodeResults)
    {
        MainThread.BeginInvokeOnMainThread(() =>
            Console.WriteLine($"Found: {barcode.DisplayValue}"));
    }
}
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
    For Each barcode In e.BarcodeResults
        MainThread.BeginInvokeOnMainThread(Sub()
                                               Console.WriteLine($"Found: {barcode.DisplayValue}")
                                           End Sub)
    Next
End Sub
$vbLabelText   $csharpLabel

IronBarcode 方法:

using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var options = new BarcodeReaderOptions
    {
        Speed = ReadingSpeed.Balanced,
        ExpectMultipleBarcodes = true
    };

    var results = BarcodeReader.Read(ms.ToArray(), options);
    foreach (var result in results)
        Console.WriteLine($"{result.Format}: {result.Value}");
}
using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var options = new BarcodeReaderOptions
    {
        Speed = ReadingSpeed.Balanced,
        ExpectMultipleBarcodes = true
    };

    var results = BarcodeReader.Read(ms.ToArray(), options);
    foreach (var result in results)
        Console.WriteLine($"{result.Format}: {result.Value}");
}
Imports IronBarCode
Imports System.IO

Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
    Dim photo = Await MediaPicker.CapturePhotoAsync()
    If photo Is Nothing Then Return

    Using stream = Await photo.OpenReadAsync()
        Using ms As New MemoryStream()
            Await stream.CopyToAsync(ms)

            Dim options As New BarcodeReaderOptions With {
                .Speed = ReadingSpeed.Balanced,
                .ExpectMultipleBarcodes = True
            }

            Dim results = BarcodeReader.Read(ms.ToArray(), options)
            For Each result In results
                Console.WriteLine($"{result.Format}: {result.Value}")
            Next
        End Using
    End Using
End Sub
$vbLabelText   $csharpLabel

ExpectMultipleBarcodes = true 告訴讀者找到第一個條碼後繼續掃描。 沒有此選項,調用在第一個匹配時返回,這對單條碼場景更快。

iOS UPC-A 修復:移除正常化變通方案

如果您的程式碼庫有UPC-A 開頭零的變通方案,完全刪除它。IronBarcode返回正確的12 位值,無需任何手動干預。

BarcodeScanning.MAUI 方法——變通方法到位:

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode == null) return;

    var value = barcode.DisplayValue;

    // Workaround: Apple Vision returns 13 digits for UPC-A
    if (barcode.BarcodeFormat == BarcodeFormats.Upca && value.Length == 13)
        value = value.Substring(1);

    ProcessBarcode(value, barcode.BarcodeFormat.ToString());
}
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode == null) return;

    var value = barcode.DisplayValue;

    // Workaround: Apple Vision returns 13 digits for UPC-A
    if (barcode.BarcodeFormat == BarcodeFormats.Upca && value.Length == 13)
        value = value.Substring(1);

    ProcessBarcode(value, barcode.BarcodeFormat.ToString());
}
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
    Dim barcode = e.BarcodeResults.FirstOrDefault()
    If barcode Is Nothing Then Return

    Dim value = barcode.DisplayValue

    ' Workaround: Apple Vision returns 13 digits for UPC-A
    If barcode.BarcodeFormat = BarcodeFormats.Upca AndAlso value.Length = 13 Then
        value = value.Substring(1)
    End If

    ProcessBarcode(value, barcode.BarcodeFormat.ToString())
End Sub
$vbLabelText   $csharpLabel

IronBarcode 方法——無需變通方案:

using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var first = results.FirstOrDefault();
    if (first == null) return;

    // result.Value is the correct 12-digit UPC-A — no normalization needed
    ProcessBarcode(first.Value, first.Format.ToString());
}
using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var first = results.FirstOrDefault();
    if (first == null) return;

    // result.Value is the correct 12-digit UPC-A — no normalization needed
    ProcessBarcode(first.Value, first.Format.ToString());
}
Imports IronBarCode
Imports System.IO
Imports System.Linq
Imports System.Threading.Tasks

Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
    Dim photo = Await MediaPicker.CapturePhotoAsync()
    If photo Is Nothing Then Return

    Using stream = Await photo.OpenReadAsync()
        Using ms As New MemoryStream()
            Await stream.CopyToAsync(ms)

            Dim results = BarcodeReader.Read(ms.ToArray())
            Dim first = results.FirstOrDefault()
            If first Is Nothing Then Return

            ' result.Value is the correct 12-digit UPC-A — no normalization needed
            ProcessBarcode(first.Value, first.Format.ToString())
        End Using
    End Using
End Sub
$vbLabelText   $csharpLabel

刪除任何以BarcodeFormats.UpcaSubstring(1) 配對的匹配——那些程式碼在遷移後是無效的。

新增文件和PDF 支持

BarcodeScanning.Native.Maui 沒有文件或PDF 輸入的對應。 如果這是遷移時滿足的新需求:

BarcodeScanning.MAUI 方法:

//否equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs
//否equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs
'否equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs
$vbLabelText   $csharpLabel

IronBarcode 方法:

using IronBarCode;

// Read from a file the user picked with FilePicker
private async void ReadFileButton_Clicked(object sender, EventArgs e)
{
    var file = await FilePicker.PickAsync(new PickOptions
    {
        PickerTitle = "Select image or PDF"
    });
    if (file == null) return;

    var results = BarcodeReader.Read(file.FullPath);
    foreach (var result in results)
        ResultLabel.Text += $"\n{result.Format}: {result.Value}";
}

// Read barcodes from a PDF directly — no intermediate image step
private void ReadPdfBarcodes()
{
    var results = BarcodeReader.Read("shipment-manifest.pdf");
    foreach (var result in results)
        Console.WriteLine($"{result.Format}: {result.Value}");
}
using IronBarCode;

// Read from a file the user picked with FilePicker
private async void ReadFileButton_Clicked(object sender, EventArgs e)
{
    var file = await FilePicker.PickAsync(new PickOptions
    {
        PickerTitle = "Select image or PDF"
    });
    if (file == null) return;

    var results = BarcodeReader.Read(file.FullPath);
    foreach (var result in results)
        ResultLabel.Text += $"\n{result.Format}: {result.Value}";
}

// Read barcodes from a PDF directly — no intermediate image step
private void ReadPdfBarcodes()
{
    var results = BarcodeReader.Read("shipment-manifest.pdf");
    foreach (var result in results)
        Console.WriteLine($"{result.Format}: {result.Value}");
}
Imports IronBarCode

' Read from a file the user picked with FilePicker
Private Async Sub ReadFileButton_Clicked(sender As Object, e As EventArgs)
    Dim file = Await FilePicker.PickAsync(New PickOptions With {
        .PickerTitle = "Select image or PDF"
    })
    If file Is Nothing Then Return

    Dim results = BarcodeReader.Read(file.FullPath)
    For Each result In results
        ResultLabel.Text &= vbCrLf & $"{result.Format}: {result.Value}"
    Next
End Sub

' Read barcodes from a PDF directly — no intermediate image step
Private Sub ReadPdfBarcodes()
    Dim results = BarcodeReader.Read("shipment-manifest.pdf")
    For Each result In results
        Console.WriteLine($"{result.Format}: {result.Value}")
    Next
End Sub
$vbLabelText   $csharpLabel

IronBarcode PDF 閱讀文件 涵蓋了多頁PDF 支持和頁範圍選擇。

伺服器端條碼處理

如果您的應用程式有後端ASP.NET API 同樣需要條碼處理,相同的BarcodeReader.Read() 調用可以在那裡無需修改地運行。 BarcodeScanning.Native.Maui 沒有伺服器端對應。

BarcodeScanning.MAUI 方法:

//否equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
// and cannot run in a server process
//否equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
// and cannot run in a server process
'否equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
' and cannot run in a server process
$vbLabelText   $csharpLabel

IronBarcode 方法:

using IronBarCode;

// ASP.NET endpoint — reads barcodes from an uploaded file
[HttpPost("scan")]
public async Task<IActionResult> ScanBarcode(IFormFile file)
{
    using var ms = new MemoryStream();
    await file.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
    return Ok(values);
}
using IronBarCode;

// ASP.NET endpoint — reads barcodes from an uploaded file
[HttpPost("scan")]
public async Task<IActionResult> ScanBarcode(IFormFile file)
{
    using var ms = new MemoryStream();
    await file.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
    return Ok(values);
}
Imports IronBarCode
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
Imports System.Threading.Tasks

' ASP.NET endpoint — reads barcodes from an uploaded file
<HttpPost("scan")>
Public Async Function ScanBarcode(file As IFormFile) As Task(Of IActionResult)
    Using ms As New MemoryStream()
        Await file.CopyToAsync(ms)

        Dim results = BarcodeReader.Read(ms.ToArray())
        Dim values = results.Select(Function(r) New With {Key .Value = r.Value, Key .Format = r.Format.ToString()})
        Return Ok(values)
    End Using
End Function
$vbLabelText   $csharpLabel

相同的包,同樣的API,相同的行為——在移動和伺服器。

生成條碼

BarcodeScanning.Native.Maui 沒有生成API。IronBarcode生成多種格式。

BarcodeScanning.MAUI 方法:

//否equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes
//否equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes
'否equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes
$vbLabelText   $csharpLabel

IronBarcode 方法:

using IronBarCode;

// QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500)
    .SaveAsPng("qr.png");

// Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
    .ResizeTo(400, 100)
    .SaveAsPng("label.png");

// Get bytes for returning from an API or storing in a database
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
    .ToPngBinaryData();
using IronBarCode;

// QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500)
    .SaveAsPng("qr.png");

// Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
    .ResizeTo(400, 100)
    .SaveAsPng("label.png");

// Get bytes for returning from an API or storing in a database
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
    .ToPngBinaryData();
Imports IronBarCode

' QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500) _
    .SaveAsPng("qr.png")

' Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128) _
    .ResizeTo(400, 100) _
    .SaveAsPng("label.png")

' Get bytes for returning from an API or storing in a database
Dim barcodeBytes As Byte() = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128) _
    .ToPngBinaryData()
$vbLabelText   $csharpLabel

IronBarcode 生成文件 涵蓋了所有支持的格式和樣式選項。

BarcodeScanning.MAUI API 到IronBarcode 映射參考

BarcodeScanning.Native.Maui IronBarcode
CameraView XAML 控制 移除——使用Button + MediaPicker.CapturePhotoAsync()
OnDetectionFinished 事件 BarcodeReader.Read(imageBytes) 返回值
OnDetectionFinishedEventArg e IEnumerable 的結果來自BarcodeReader.Read()
e.BarcodeResults 返回 BarcodeReader.Read() 的值
e.BarcodeResults.FirstOrDefault() results.FirstOrDefault()
barcode.DisplayValue result.Value
barcode.BarcodeFormat result.Format
BarcodeFormats="All" 自動檢測—無需配置
CameraEnabled="True" await MediaPicker.CapturePhotoAsync()
僅限iOS + Android iOS、Android、Windows、macOS MAUI
沒有文件輸入 BarcodeReader.Read(filePath)
沒有PDF 輸入 BarcodeReader.Read("document.pdf")
沒有生成 BarcodeWriter.CreateBarcode() / QRCodeWriter.CreateQrCode()
iOS UPC-A 返回13 位數 返回正確的12 位數—無需正常化
PDF417 不可靠 支持

常見遷移問題及解決方案

問題1:實時取景器體驗丟失

BarcodeScanning.MAUI: CameraView 控制內嵌實時相機預覽直接在MAUI 頁面內。 使用者能看到相機反饋並對準條碼——偵測自動發生無需按鈕按壓。

解決方案: MediaPicker.CapturePhotoAsync() 會顯示平台相機螢幕取而代之。 對於大多數業務工作流程這是可以接受的。 對於需要連續現場預覽的消費者應用程式,相機幀可直接傳遞到BarcodeReader.Read()

using IronBarCode;

// Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
// (frame capture depends on your MAUI camera frame source)
private void ProcessCameraFrame(byte[] frameBytes)
{
    var results = BarcodeReader.Read(frameBytes);
    if (results.Any())
    {
        var first = results.First();
        MainThread.BeginInvokeOnMainThread(() =>
            ResultLabel.Text = first.Value);
    }
}
using IronBarCode;

// Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
// (frame capture depends on your MAUI camera frame source)
private void ProcessCameraFrame(byte[] frameBytes)
{
    var results = BarcodeReader.Read(frameBytes);
    if (results.Any())
    {
        var first = results.First();
        MainThread.BeginInvokeOnMainThread(() =>
            ResultLabel.Text = first.Value);
    }
}
Imports IronBarCode

' Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
' (frame capture depends on your MAUI camera frame source)
Private Sub ProcessCameraFrame(frameBytes As Byte())
    Dim results = BarcodeReader.Read(frameBytes)
    If results.Any() Then
        Dim first = results.First()
        MainThread.BeginInvokeOnMainThread(Sub()
                                               ResultLabel.Text = first.Value
                                           End Sub)
    End If
End Sub
$vbLabelText   $csharpLabel

這需要將相機幀源單獨連接到IronBarcode。 在採取這一步之前檢查現場預覽是否真實需要或系統相機UI 已足夠。

問題2:e.BarcodeResults 屬性名称和列舉值變更

BarcodeScanning.MAUI: barcode.DisplayValue 返回解碼後的字串; barcode.BarcodeFormat 返回BarcodeScanning 程式庫列舉值。

解決方案: 取代 DisplayValueresult.Valueresult.Format。 重複模式相同:

// Before
foreach (var barcode in e.BarcodeResults)
    Console.WriteLine(barcode.DisplayValue);

// After
var results = BarcodeReader.Read(imageBytes);
foreach (var result in results)
    Console.WriteLine(result.Value);
// Before
foreach (var barcode in e.BarcodeResults)
    Console.WriteLine(barcode.DisplayValue);

// After
var results = BarcodeReader.Read(imageBytes);
foreach (var result in results)
    Console.WriteLine(result.Value);
' Before
For Each barcode In e.BarcodeResults
    Console.WriteLine(barcode.DisplayValue)
Next

' After
Dim results = BarcodeReader.Read(imageBytes)
For Each result In results
    Console.WriteLine(result.Value)
Next
$vbLabelText   $csharpLabel

問題3:執行緒為UI 更新導航

BarcodeScanning.MAUI: OnDetectionFinished 在背景執行緒上觸發,所以所有UI 更新需要MainThread.BeginInvokeOnMainThread()

解決方案: 使用MediaPicker + async 模式,在await 返回后,繼續會回到呼叫上下文——通常是主執行緒。 MainThread.BeginInvokeOnMainThread() 包裹在結果顯示周圍的包裝通常可以移除,簡化處理程式程式碼。

問題4:MAUI 相機權限

BarcodeScanning.MAUI: 權限包新增到Info.plist自動作為設置的一部分。

解決方案: 使用IronBarcode 的MediaPicker,標準MAUI相機權限必須手動存在。 這些是任何MAUI 應用程式需要的相同權限,用於MediaPicker.CapturePhotoAsync() 並通常已在適當位置。 在裝置上測試之前,驗證AndroidManifest.xml 中被聲明,Info.plist 中被設置。

BarcodeScanning.MAUI 遷移清單

遷移前任務

在做任何改變之前,運行這些搜尋以查找所有BarcodeScanning.Native.Maui 用法:

grep -rn "using BarcodeScanning" --include="*.cs" .
grep -rn "using BarcodeScanning" --include="*.xaml" .
grep -rn "CameraView" --include="*.cs" .
grep -rn "CameraView" --include="*.xaml" .
grep -rn "OnDetectionFinished" --include="*.cs" .
grep -rn "OnDetectionFinishedEventArg" --include="*.cs" .
grep -rn "e\.BarcodeResults" --include="*.cs" .
grep -rn "DisplayValue" --include="*.cs" .
grep -rn "BarcodeFormats\.Upca" --include="*.cs" .
grep -rn "scanner:" --include="*.xaml" .
grep -rn "using BarcodeScanning" --include="*.cs" .
grep -rn "using BarcodeScanning" --include="*.xaml" .
grep -rn "CameraView" --include="*.cs" .
grep -rn "CameraView" --include="*.xaml" .
grep -rn "OnDetectionFinished" --include="*.cs" .
grep -rn "OnDetectionFinishedEventArg" --include="*.cs" .
grep -rn "e\.BarcodeResults" --include="*.cs" .
grep -rn "DisplayValue" --include="*.cs" .
grep -rn "BarcodeFormats\.Upca" --include="*.cs" .
grep -rn "scanner:" --include="*.xaml" .
SHELL

記錄每個命中。 註明哪些文件包含CameraView XAML 用法(需要XAML 變更)與僅包含後端程式碼變更的文件。 識別任何在遷移後必須被刪除的UPC-A 正規化變通方案。

程式碼更新任務

  1. 移除BarcodeScanning.Native.Maui NuGet 包
  2. 安裝IronBarcode NuGet 包
  3. MauiProgram.csIronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
  4. 在所有.cs 文件中將using BarcodeScanning; 替換為using IronBarCode; 5.從所有XAML 文件中刪除xmlns:scanner="..." 命名空間聲明
  5. 將XAML 中的scanner:CameraView 控制替換為Button 觸發MediaPicker.CapturePhotoAsync()
  6. 刪除XAML 中的OnDetectionFinished="..." 事件接線
  7. async 按鈕點擊處理器使用BarcodeReader.Read() 替換OnDetectionFinished 事件處理器
  8. 全面更換result.Value
  9. 全面更換result.Format
  10. 刪除所有BarcodeFormats.Upca + Substring(1) 正規化變通方案
  11. 在多條碼檢測原先依賴e.BarcodeResults 返回多項時,將ExpectMultipleBarcodes = true 新增到BarcodeReaderOptions
  12. 在結果顯示程式碼中刪除即時模式無需的MainThread.BeginInvokeOnMainThread() 包裹
  13. 驗證AndroidManifest.xmlInfo.plist 相機權限是否存在

遷移後測試

  • 驗證iOS 條碼掃描是否有效,UPC-A 值是否作為12 命字串返回而無開頭零
  • 驗證Android 條碼掃描是否生成正確的值,對於應用程式中使用的所有格式
  • 如果Windows 是構建目標,驗證Windows MAUI 條碼掃描是否有效
  • 如果使用,對照真實運送標籤、駕駛執照或登機證測試PDF417 掃描
  • ExpectMultipleBarcodes = true 測試多條碼場景,確認圖像中所有條碼返回
  • 驗證文件選擇器掃描(BarcodeReader.Read(filePath))在所有MAUI 目標上是否有效
  • 如果這是隨遷移一起新增的新功能,驗證PDF 條碼閱讀是否有效
  • 如果新增了後端組件,確認伺服器端BarcodeReader.Read() 生成正確結果
  • 運行任何現有的自動化測試,並將條碼值輸出與遷移前的基準作比較

遷移到IronBarcode的主要優勢

全面Windows MAUI 支持:IronBarcode可以運行在所有四個MAUI 目標上—iOS、Android、Windows 和macOS—使用相同的程式碼和相同的包。 Windows 不需要特定的条碼實現,並且在應用程式程式碼中不需要#if WINDOWS塊。

任何輸入來源: BarcodeReader.Read() 接受文件路徑、字節陣列、流和PDF 文件。 任何條碼場景——相機拍攝、文件上傳、畫廊圖像、伺服器端PDF 處理——都使用相同的靜態方法與相同的結果型別。

正確的UPC-A值:IronBarcode在iOS 上返回正確的12 位UPC-A 值,無需應用程式中的任何正規化程式碼。 由於BarcodeScanning.Native.Maui 的行為而以領先零儲存的歷史UPC-A 資料不會影響遷移後讀取的數值準確性。

可靠的PDF417: PDF417 完全受支持並能夠可靠地讀取。 運送標簽、駕駛執照和登機證在BarcodeScanning.Native.Maui 的GitHub 問題中記錄的"大多數掃描從未發生過"限制下無需掃描。

條碼生成: BarcodeWriter.CreateBarcode()QRCodeWriter.CreateQrCode() 生成Code128、QR、DataMatrix 和其他格式作為PNG 文件或字節陣列。 生成和閱讀可從相同的包中獲得,無需額外的依賴。

伺服器端部署: 相同的BarcodeReader.Read() 調用在ASP.NET、Azure Functions、Docker 容器和AWS Lambda 中運行。 移動和伺服器的條碼邏輯可以共享相同的API、相同的格式支持和相同的結果型別,而無需維持兩個獨立的條碼實現。

常見問題

為什麼我應該從 BarcodeScanning.MAUI 遷移到 IronBarcode?

常見的理由包括簡化授權(去除SDK +運行時鑰匙的複雜性)、消除吞吐量限制、獲得原生PDF支持、改善Docker/CI/CD部署,並減少生產程式碼中的API樣板。

我應如何用 IronBarcode 替換 BarcodeScanning.MAUI 的 API 呼叫?

用IronBarCode.License.LicenseKey = "key"替換實例建立和授權樣板。用BarcodeReader.Read(path)替換讀取呼叫,用BarcodeWriter.CreateBarcode(data, encoding)替換寫入呼叫。靜態方法不需要實例管理。

從 BarcodeScanning.MAUI 遷移到 IronBarcode 會有多少程式碼改變?

大多數遷移會導致較少的程式碼行。授權樣板、實例構造函式和顯式格式配置被移除。核心讀/寫操作映射為較短的IronBarcode等價物,且結果物件更清晰。

遷移期間我是否需要同時安裝 BarcodeScanning.MAUI 和 IronBarcode?

不需要。大多數遷移是直接替換而不是並行操作。一次遷移一個服務類,替換NuGet引用,並更新實例化和API呼叫模式後再移動到下一個類。

IronBarcode的NuGet包名稱是什麼?

包名是'IronBarCode'(大寫B和C)。可以用'Install-Package IronBarCode'或'dotnet add package IronBarCode'安裝。程式碼中的using指令是'using IronBarCode;'。

與 BarcodeScanning.MAUI 相比,IronBarcode 如何簡化 Docker 部署?

IronBarcode是沒有外部SDK文件或掛載許可配置的NuGet封裝。在Docker中,設置IRONBARCODE_LICENSE_KEY環境變數,包在啟動時處理許可驗證。

從 BarcodeScanning.MAUI 遷移後,IronBarcode 能自動檢測所有條碼格式嗎?

是的。IronBarcode自動檢測所有支持的格式的符號學。不需要顯式的BarcodeTypes枚舉。如果格式已經知道並且性能很重要,BarcodeReaderOptions允許限制搜索空間作為優化。

IronBarcode是否可以不使用單獨的庫讀取PDF中的條碼?

可以。BarcodeReader.Read("document.pdf")原生處理PDF文件。結果包括每個條碼發現的頁碼、格式、值和置信度。不需要外部PDF渲染步驟。

IronBarcode如何處理並行條碼處理?

IronBarcode的靜態方法是無狀態且執行緒安全的。直接使用Parallel.ForEach遍歷文件列表,不需要每個執行緒的實例管理。BarcodeReaderOptions.MaxParallelThreads控制內部執行緒預算。

從 BarcodeScanning.MAUI 遷移到 IronBarcode 時,哪些結果屬性會改變?

常見的重命名:BarcodeValue變為Value,BarcodeType變為Format。IronBarcode結果還新增了Confidence和PageNumber。整個解決方案的搜索和替換可處理現有結果處理程式碼中的重新命名。

我如何在CI/CD管道中設置IronBarcode授權?

將IRONBARCODE_LICENSE_KEY作為管道機密儲存,在應用程式啟動程式碼中分配IronBarCode.License.LicenseKey。一個機密涵蓋所有環境,包括開發、測試、分期和生產。

IronBarcode是否支持生成帶有自定義樣式的QR碼?

支持。QRCodeWriter.CreateQrCode()支持通過ChangeBarCodeColor()自定義顏色,通過AddBrandLogo()嵌入logo,可配置錯誤校正級別,以及包括PNG、JPG、PDF和流在內的多種輸出格式。

Curtis Chau
技術作家

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

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

Iron 支援團隊

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