フッターコンテンツにスキップ
IRONBARCODEの使用

ASP.NETバーコード スキャナー: IronBarcodeを使用したファイルアップロードと REST API

IronBarcodeを使用すると、 ASP.NETでのバーコードスキャンが簡単になります。NuGetNuGetでインストールし、BarcodeReader.Read() を呼び出すだけで、タイプ、信頼度、位置データを含むデコードされた値をワンステップで取得できます。複雑な設定は不要です。

バーコードスキャンは現代のウェブアプリケーションにおける標準的な要件であり、在庫管理、文書処理、チケット検証などのワークフローを支える基盤となっている。 GS1によると、バーコードは世界中で毎日60億件以上の取引に使用されており、この数字はあらゆるビジネスシステムにとって正確なバーコード読み取りがいかに重要であるかを物語っている。 ISO/IEC 15415規格は2次元バーコードシンボルの品質指標を定義しており、 ISO/IEC 15416規格は1次元リニアバーコードを対象としています。IronBarcodeはどちらの規格もネイティブにサポートしています。

このガイドでは、 IronBarcodeを使用してASP.NET Coreアプリケーションに信頼性の高いバーコードスキャン機能を追加する方法を説明します。インストール、ファイルアップロード処理、REST API 統合、および本番環境へのデプロイパターンについて解説します。 最終的には、 Razorページのファイルアップロードスキャナーと、任意のクライアントからbase64エンコードされた画像を受け入れるJSON APIエンドポイントの両方の動作するコードが完成します。

ASP.NETプロジェクトにIronBarcodeをインストールするにはどうすればよいですか?

使い始めるのにかかる時間はほんの数分です。 このライブラリは、 ASP.NET Coreと従来のASP.NET MVCアプリケーションの両方をサポートしているため、さまざまなプロジェクトタイプに対応できます。Enterprise環境へのデプロイも、 AzureAWS LambdaDockerコンテナのいずれでも問題なく動作します。 このライブラリの機械学習を活用した検出機能は、高度な画像補正を自動的に適用することで、扱いの難しいバーコード画像にも対応します。これは、照明条件が変化する中でモバイルカメラで撮影した写真を処理する場合に特に役立ちます。

NuGetパッケージマネージャー経由でのインストール

Visual StudioでPackage Manager Consoleを開き、実行してください:

Install-Package BarCode
Install-Package BarCode
SHELL

または、 .NET CLI を使用してください。

dotnet add package BarCode
dotnet add package BarCode
SHELL

または、Visual Studio のNuGetパッケージ マネージャーの UI で"BarCode"を検索し、"インストール"をクリックします。 このパッケージはすべての依存関係を自動的に管理します。

プラットフォーム固有のデプロイメントの場合は、対象環境向けに最適化されたプラットフォーム固有のNuGetパッケージの使用を検討してください。 このライブラリは、さまざまな導入シナリオに対応できるよう、標準パッケージとBarCode.Slimパッケージの両方を提供しています。 インストール手順の詳細については、 IronBarcodeのインストールガイドを参照してください。

プロジェクトの設定

インストールが完了したら、C#ファイルに必要なusingステートメントを追加してください。

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

このインポートにより、IronBarcodeのバーコード読み取りおよび生成機能をすべて利用できるようになります。 このライブラリは、QRコード、Code 128、Code 39、Data Matrix、PDF417など、30種類以上のバーコード形式をサポートしています。サポートされているバーコード形式の完全なリストをご覧になり、ご使用の用途との互換性をご確認ください。

インストールに関する問題のトラブルシューティングについては、 NuGetパッケージのトラブルシューティング ガイドを参照するか、専門的なサポートを依頼するためにエンジニアリング リクエストを送信してください。

適切なアーキテクチャパターンを選択する

ASP.NETでバーコードスキャンを実装する場合、主に2つのアーキテクチャ上のアプローチがあります。 これらのパターンを理解することで、それぞれの用途に最適なバーコードリーダーの設定を選択できるようになります。

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

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

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

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

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

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

Dim results = BarcodeReader.Read(stream, options)

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

サーバーサイド方式を採用することで、画像処理を最大限に制御でき、すべてのブラウザで一貫して動作します。 サーバーがすべての画像を処理すると、クリーンな監査証跡も得られます。スキャンされたすべてのバーコードはアプリケーション層を通過し、そこでログに記録したり、データベースと照合して検証したり、下流のワークフローをトリガーしたりできます。 このパターンは、医療、物流、製造業など、すべてのスキャンを記録する必要がある規制の厳しい業界に特に適しています。

クライアント側のカメラキャプチャ統合に関しては、最新のブラウザはカメラアクセス用のMediaDevices APIをサポートしており、これはREST APIを介してIronBarcodeのサーバー側処理と組み合わせることができます(詳細は本ガイドの後半で説明します)。サーバー側処理を選択することで、セキュリティモデルも簡素化されます。機密性の高い処理ロジックがブラウザに公開されることはなく、すべての検証はアプリケーションの境界内で行われます。

クライアント側とサーバー側のバーコードスキャンにおけるトレードオフ
アスペクト クライアント側キャプチャ+サーバー処理 純粋なサーバーサイド処理
最適 カメラによるリアルタイムスキャン バッチ処理、ファイルアップロード
ブラウザのサポート 最新のブラウザのみ すべてのブラウザ
ユーザーエクスペリエンス 即時フィードバック 標準アップロードフロー
セキュリティモデル より複雑な(CORS、認証) 分かりやすい
帯域幅使用量 (デバイス上で前処理済み) より高い(生画像のアップロード)

ファイルアップロードによるバーコードスキャンはどのように実装しますか?

ファイルアップロードによるスキャンは、 ASP.NET Webアプリケーションにおいて最も一般的なバーコード処理のシナリオです。 このパターンは、請求書、配送ラベル、またはバーコードが埋め込まれたあらゆる文書の処理に有効です。 処理能力を向上させるには、非同期バーコード読み取りを実装して、複数のアップロードを同時に処理することを検討してください。

アップロードフォームの作成

ASP.NETビューでレスポンシブなHTMLフォームを作成します。

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

capture="environment" 属性はモバイルデバイスの背面カメラをアクティブ化し、 JavaScriptを使用せずにネイティブカメラのようなエクスペリエンスをユーザーに提供します。

セキュアなバックエンド処理の実装

コントローラアクションは、ファイル検証、メモリストリーム処理、および結果のフォーマット処理を行います。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            Dim results = BarcodeReader.Read(stream, options)

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

    Return View()
End Function
$vbLabelText   $csharpLabel

この実装では、処理前にファイルの種類を検証し、メモリ ストリームからバーコードを読み取り、検出されたすべての結果を返します。 IronBarcodeは、複数ページのTIFFやGIFPDFドキュメントなど、さまざまな画像フォーマットを処理するため、フォーマット固有の処理コードが不要になります。

スキャンされた入力と出力の様子

Code 128 バーコード エンコーディング URL 'https://ironsoftware.com/csharp/barcode/' は、 ASP.NETバーコード リーダー アプリケーションで正確にスキャンできるように、機械で読み取り可能なバーと、その下に人間が読み取れるテキストを表示します。

上記の例は、標準的なCode 128バーコードを示しています。これは、出荷や在庫管理のアプリケーションでよく使用される形式です。 スキャン後、結果画面にはデコードされた値と信頼度メタデータが表示されます。

 ASP.NET Core Webアプリケーションインターフェイスには、デコードされたCode128バーコード値と信頼度スコアメタデータを表示するファイルアップロードフォームとともに、バーコードスキャンの成功結果が表示されます。

IronBarcodeは、アップロードされた画像内で検出された各バーコードについて、バーコードの種類、デコードされた値、信頼度スコア、および位置データを返します。

バーコードスキャン用のREST APIはどのように構築すればよいですか?

最新のASP.NETアプリケーションは、多くの場合、REST APIを通じてバーコードスキャン機能を公開しており、モバイルアプリ、シングルページアプリケーション、またはサードパーティサービスとの統合を可能にしている。 このパターンは、クライアント側でのカメラキャプチャとサーバー側での処理をサポートします。

バーコードAPIのセキュリティに関する考慮事項

コントローラーを作成する前に、セキュリティ層の設計を計画してください。 バーコードデータには任意の内容が含まれる可能性があるため、入力内容は必ず検証してください。 IronBarcodeのセキュリティガイドラインに従って、完全な保護を実現してください。

-入力検証:バーコードの内容を保存または処理する前に、サニタイズする -レート制限: ASP.NET Core の組み込みレート制限ミドルウェアを使用して、API の悪用を防止します。 -認証:JWTトークンまたはAPIキーでエンドポイントを保護する

  • HTTPSの強制適用:すべてのバーコードAPIトラフィックはTLS経由で送信される必要があります
  • CORSポリシー:スキャンエンドポイントを呼び出すことができるオリジンを制限します -ライセンスキーの管理: ライセンスキーを正しく適用し、本番環境向けにweb.configで設定します。

本番環境用APIコントローラーの構築

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

このエンドポイントは、HTTP経由で画像を送信するための標準フォーマットであるbase64エンコードされた画像を受け付けます。レスポンスには、バーコードの種類、デコードされた値、信頼度スコア、および位置が含まれます。 大量処理の場合は、バッチバーコード処理読み取り速度最適化オプションを確認してください。

APIは複数のバーコードをどのように処理しますか?

 IronBarcodeが本番環境で同時に処理するQRコード、Code128、およびDataMatrixシンボル体系を示す、ABCとラベル付けされた3つの異なるバーコード形式

IronBarcodeは、1つの画像内の複数のバーコードを1回の呼び出しで処理し、結果の配列を返します。 レスポンスの各エントリには位置情報が含まれているため、クライアントアプリケーションは検出されたバーコードを画面上で強調表示できます。

ブラウザの開発者ツールのネットワークタブには、検出された3つのバーコードの配列と、タイプ、値、信頼度、位置座標を含む完全なメタデータを含む、JSON API応答が正常に返されたことが示されています。

構造化されたJSONレスポンスは、クライアントアプリケーションが追加の検索を行うことなく、バーコード結果を処理および表示するために必要なすべての情報を提供します。

難易度の高いバーコード画像にはどのように対処していますか?

実際のバーコードスキャンでは、角度のついた写真、照明条件の悪い写真、部分的に破損したバーコードなど、不完全な画像を扱うことが頻繁にあります。 IronBarcodeは、高度な画像処理機能機械学習による信頼度閾値によって、これらのシナリオに対応します。

一般的なスキャン問題の診断

修正を適用する前に、問題がどのカテゴリーに該当するかを特定してください。 生産現場で発生するスキャンエラーのほとんどは、以下の5つのグループのいずれかに分類されます。画像品質の問題(ぼやけ、ノイズ、低解像度)、幾何学的問題(回転、歪み、遠近法の歪み)、損傷の問題(ラベルの破れ、インクのにじみ)、環境の問題(まぶしさ、影、照明の不均一性)、そしてリーダーが実際には存在しないバーコードを検出する誤検出です。

カテゴリを把握することで、すべての画像に対して不要な処理を実行することなく、適切なフィルターの組み合わせと読み込み速度を選択できます。 ほとんどのウェブアプリケーションのシナリオでは、ReadingSpeed.Balanced および AutoRotate = true で始まるものが大部分のケースをカバーします。 最初のパスで結果が返されない場合にのみ、ExtremeDetail にエスカレーションしてください。

以下のコードに示すマルチパス方式は、この階層型戦略を実装しています。 高速な初回処理により、一般的な画像は迅速に処理され、通常のケースでは平均レイテンシが低く抑えられます。 詳細な2回目の処理は、1回目の処理が失敗した場合にのみ実行されるため、追加の処理コストは実際に必要な場合にのみ発生します。 このパターンは、通常の負荷条件下ではASP.NETエンドポイントの応答性を維持しつつ、複雑なエッジケースにも確実に対応します。

バーコードスキャンにおける一般的な問題とその解決策
問題 症状 ソリューション
ぼやけた画像 信頼度スコアが低い、読み取り漏れ `SharpenFilter`を適用し、 `ExtremeDetail`速度を上げます。
回転したバーコード バーコードが全く検出されませんでした `AutoRotate = true`
破損したバーコード 部分的な読み取り、誤った値 エラー訂正を有効にするには、 `RemoveFalsePositive`使用してください。
コントラストが低い 検出結果の不一致 `ContrastFilter`と`BrightnessFilter`を適用する
パフォーマンスが遅すぎる アップロード時のレイテンシが高い `ReadingSpeed.Faster`を使用し、マルチスレッドを有効にします。

マルチパス画像処理の実装

難易度の高い画像の場合、段階的な処理アプローチを採用することで、簡単な画像でのパフォーマンスを損なうことなく、最良の結果が得られます。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        Dim results = BarcodeReader.Read(imageStream, fastOptions)

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

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

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

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

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

BarcodeReaderOptionsクラスは、スキャンに関するあらゆる側面をきめ細かく制御できます。 設定 AutoRotate はあらゆる角度から撮影された画像に対応し、画像フィルターはぼやけたバーコードやコントラストの低いバーコードの鮮明度を向上させます。 詳細な設定については、バーコードリーダーの設定例PDF固有のリーダー設定を参照してください。

PDFを扱う際は、 PDFにバーコードを印字するか、 PDF文書としてバーコードを作成することを検討してください。 大量処理の場合、非同期処理とマルチスレッド処理を有効にすることで、スループットが大幅に向上します。

ブラウザ互換性とフォールバック戦略の追加

多様なブラウザに対応するには、段階的な機能強化が必要です。 Android およびデスクトップ版の最新のブラウザである Chrome、Edge、Firefox は、カメラアクセス用の MediaDevices.getUserMedia() API をサポートしています。 iOS版Safariはバージョン11以降で対応しています。 古いEnterpriseブラウザ、IE11互換モード、および一部の厳格な企業環境では、カメラへのアクセスがまったくサポートされない場合があるため、代替のファイルアップロードパスは常に機能するようにしておく必要があります。

推奨される方法は、ユーザーエージェントの検出ではなく、実行時に特徴検出を行い、それに応じてカメラインターフェースを表示または非表示にすることです。 カメラ機能を備えたインターフェースから始め、必要に応じてファイルアップロードにスムーズに切り替えます。

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

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

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

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

Blazorとの統合により、コンポーネントベースのアプローチを好む場合、最小限の設定で最新のWebアプリケーションをサポートできます。 デプロイメントのトラブルシューティングについては、ランタイムコピー例外ガイドを参照してください。

次のステップは何ですか?

IronBarcodeを使えば、 ASP.NETでのバーコードスキャンは簡単です。 NuGetパッケージを 1 つインストールし、BarcodeReader.Read() を呼び出すだけで、他のライブラリでは処理が難しい実際の画像を含む 30 種類以上のフォーマットで信頼性の高いデコード結果が得られます。

この基盤をさらに発展させるために、以下のリソースをご活用ください。

-バーコード読み取りチュートリアル-- あらゆるスキャンシナリオに対応した詳細ガイド -バーコード生成-- プログラムでバーコードとQRコードを作成します

まずは無料トライアルライセンスで、 ASP.NETアプリケーションでIronBarcodeを制限なくテストしてみましょう。 トライアル版では、マルチフォーマット検出、画像補正、およびこのガイドで紹介されているREST APIパターンを含むすべての機能にフルアクセスできます。そのため、製品版ライセンスを購入する前に、ご自身の画像でパフォーマンスを評価できます。 .NET MAUIモバイルアプリでデバイス上でのスキャンが必要な場合は、iOS および Android ターゲット向けに同じ API を拡張した.NET MAUIバーコードスキャナのチュートリアルを参照してください。

よくある質問

ASP.NETアプリケーションにおけるバーコードスキャンの主な使用目的は何ですか?

ASP.NETアプリケーションにおけるバーコードスキャンは主に、在庫管理システムを強化し、イベントでのチケット処理を行い、紙の書類をデジタル化するために使用され、効率を向上させエラーを減少させます。

IronBarcodeはASP.NETにおけるバーコードスキャンをどのように容易にしますか?

IronBarcode は、ウェブアプリケーションに簡単に統合できる信頼性が高く効率的なコンポーネントを提供することで、ASP.NET におけるバーコードスキャンのプロセスを簡素化し、開発者がスキャン機能を迅速に実装できるようにします。

IronBarcodeを使用してスキャンできるバーコードの種類は何ですか?

IronBarcodeは、伝統的な線形バーコードや現代的な2Dバーコードを含む多様なバーコードフォーマットのスキャンをサポートしており、多様なアプリケーションとの互換性を確保しています。

IronBarcodeはドキュメント処理のためのバーコードスキャンを扱えますか?

はい、IronBarcodeは埋め込まれたバーコードをスキャンすることで紙の書類をデジタル化し整理するドキュメント処理ワークフローで使用するのに適しています。

IronBarcodeは在庫管理システムに適していますか?

IronBarcodeは、バーコードをスキャンすることで製品の効率的な追跡を可能にし、操作を合理化し、エラーを最小限に抑えるため、在庫管理システムに最適な選択です。

IronBarcodeを統合することでイベントチケット処理はどのように改善されますか?

IronBarcodeを統合することで、イベントのチケットバーコードを迅速にスキャンでき、イベントでのエントリ管理を迅速かつ正確に行えます。

ASP.NETプロジェクトでIronBarcodeを使用する利点は何ですか?

ASP.NETプロジェクトでIronBarcodeを使用することで、統合のしやすさ、多様なバーコードフォーマットのサポート、アプリケーションのパフォーマンス向上など、バーコードスキャニングニーズに対応する強力なソリューションを提供する利点があります。

IronBarcodeの実装には大規模なコーディング知識が必要ですか?

いいえ、IronBarcodeは開発者フレンドリーに設計されており、コーディング知識がほとんどなくてもASP.NETアプリケーションにバーコードスキャンの機能を簡単に実装できます。

IronBarcodeはモバイルWebアプリケーションで使用できますか?

はい、IronBarcodeはモバイルWebアプリケーションにも統合でき、移動中でもバーコードスキャンが可能で、ASP.NETプロジェクトの柔軟性を向上させます。

Jordi Bardia
ソフトウェアエンジニア
Jordiは、最も得意な言語がPython、C#、C++であり、Iron Softwareでそのスキルを発揮していない時は、ゲームプログラミングをしています。製品テスト、製品開発、研究の責任を分担し、Jordiは継続的な製品改善において多大な価値を追加しています。この多様な経験は彼を挑戦させ続け、興味を持たせており、Iron Softwareで働くことの好きな側面の一つだと言います。Jordiはフロリダ州マイアミで育ち、フロリダ大学でコンピュータサイエンスと統計学を学びました。

アイアンサポートチーム

私たちは週5日、24時間オンラインで対応しています。
チャット
メール
電話してね