IRONSOFTWAREHOME
KORZYSTANIE Z IRONBARCODE

Zbuduj API czytnika kodów kreskowych w C# (Przewodnik dla deweloperów)

Curtis Chau
Curtis Chau
Updated: 28 czerwca 2026

Stwórz RESTful API skanera kodów kreskowych przy użyciu IronBarcode i ASP.NET Core, aby zarządzać kodami kreskowymi z obrazów, plików PDF i uszkodzonych skanów bez sprzętu, zapewniając niezawodną wydajność w systemach Windows, Linux i macOS.

IronBarcode umożliwia profesjonalne skanowanie kodów kreskowych za pośrednictwem interfejsów API RESTful w ASP.NET Core, przetwarzając obrazy, pliki PDF i uszkodzone skany bez zależności sprzętowych, jednocześnie obsługując wdrażanie wielopłatformowe z wbudowanymi funkcjami bezpieczeństwa i zgodności.

Czym jest Enterprise BarCode Challenge?

Wyobraź sobie, że jesteś architektem Enterprise w firmie logistycznej z listy Fortune 500. Twoje zespoły magazynowe borykają się z uszkodzonymi etykietami wysyłkowymi, dział finansowy musi przetwarzać tysiące faktur w formacie PDF z osadzonymi BARCODES-ami, a zespół ds. bezpieczeństwa IT wymaga rozwiązania, które spełnia wymogi zgodności z SOC2 bez wprowadzania zależności sprzętowych w całej globalnej infrastrukturze.

Jest to typowy scenariusz dla zespołów Enterprise, które chcą poznać możliwości interfejsu API REST firmy IronBarcode. To, co zaczęło się od prostego wymagania odczytu BarCodes, przekształciło się w kompletne rozwiązanie skanujące, które obecnie przetwarza ponad 2 miliony BarCodes miesięcznie w całej organizacji.

Tradycyjnie wymagałoby to kosztownych skanerów w każdej lokalizacji, skomplikowanego zarządzania sterownikami oraz znacznych przeglądów bezpieczeństwa. Zamiast tego stworzyli scentralizowane RESTful API, do którego każdy dział miał bezpieczny dostęp, niezależnie od tego, czy chodziło o skanowanie uszkodzonych etykiet magazynowych, czy też wyodrębnianie danych z faktur z plików PDF dostawców.

Ten samouczek poprowadzi Cię przez proces tworzenia tego samego profesjonalnego interfejsu API skanera BarCode. Dowiesz się, jak tworzyć bezpieczne punkty końcowe, które radzą sobie z rzeczywistymi wyzwaniami, takimi jak podarte etykiety, przekrzywione obrazy i dokumenty wielostronicowe. Co ważniejsze, zobaczysz, jak wdrożyć to z zachowaniem bezpieczeństwa, skalowalności i stabilności dostawców, których wymagają środowiska Enterprise.

Jak zbudować niezawodne API skanera C#?

Stworzenie Enterprise API skanera BarCode wymaga wcześniejszego uwzględnienia kilku kluczowych kwestii. Zespoły ds. bezpieczeństwa potrzebują pewności co do sposobu przetwarzania danych. Specjaliści ds. zgodności wymagają ścieżek audytu. Zespoły operacyjne wymagają niezawodności na różnych platformach. Kompletna dokumentacja IronBarcode systematycznie odpowiada na wszystkie te kwestie.

Piękno podejścia RESTful polega na jego prostocie i bezpieczeństwie. Dzięki scentralizowaniu przetwarzania BarCode za bezpiecznymi punktami końcowymi API zachowujesz pełną kontrolę nad przepływem danych. Żadne urządzenia klienckie nie wymagają bezpośredniego dostępu do logiki przetwarzania BarCode. Architektura ta w naturalny sposób wspiera model bezpieczeństwa typu zero-trust, umożliwiając jednocześnie płynną integrację z istniejącymi systemami Enterprise.

Zacznijmy od podstaw. Funkcje odczytu IronBarcode obsługują wszystkie główne formaty kodów kreskowych, z którymi może spotkać się Twoja Enterprise. Biblioteka obsługuje wszystkie rodzaje barcode'ów, od tradycyjnych barcode'ów Code 39 stosowanych w produkcji po nowoczesne kody QR wykorzystywane w kampaniach marketingowych. Przewodnik po obsługiwanych formatach BARCODE stanowi kompletne źródło informacji przydatne podczas planowania wdrożenia.

To, co sprawia, że jest to szczególnie cenne w scenariuszach Enterprise, to możliwości biblioteki w zakresie odporności na awarie. BARCODES in real life are not perfect. Ulegają one uszkodzeniu, są źle wydrukowane lub zeskanowane pod kątem. Zaawansowane przetwarzanie obrazów w IronBarcode automatycznie radzi sobie z tymi wyzwaniami, zmniejszając liczbę zgłoszeń do pomocy technicznej i poprawiając wydajność operacyjną.

Jak zainstalować i skonfigurować bibliotekę BarCode?

Wdrożenia w przedsiębiorstwach wymagają starannego rozważenia zależności i licencji. IronBarcode ułatwia to dzięki prostej instalacji NuGet i przejrzystej licencji. Oto jak rozpocząć pracę nad projektem .NET Core:

PM > Install-Package BarCode

W przypadku środowisk Enterprise o określonych wymaganiach dotyczących platformy należy zapoznać się z zaawansowanym przewodnikiem instalacji NuGet. Obejmuje to scenariusze takie jak kierowanie reklam do określonych wersji .NET lub optymalizacja pod kątem konkretnych platform.

Po zainstalowaniu sprawdź konfigurację za pomocą prostego testu. Ten kod pokazuje, że biblioteka potrafi odczytywać kody kreskowe przy minimalnej konfiguracji:

using IronBarCode;

// Verify installation with a basic barcode read
public class InstallationTest
{
    public static void VerifySetup()
    {
        try
        {
            // Test with a sample barcode image
            var result = BarcodeReader.Read("test-barcode.png");
            
            if (result.Any())
            {
                Console.WriteLine($"Success! Detected: {result.First().Value}");
                Console.WriteLine($"Format: {result.First().BarcodeType}");
                Console.WriteLine($"Confidence: {result.First().Confidence}%");
            }
            else
            {
                Console.WriteLine("No barcode detected in test image");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Setup issue: {ex.Message}");
        }
    }
}

Ten etap weryfikacji ma kluczowe znaczenie dla wdrożeń w Enterprise. Potwierdza to, że biblioteka jest poprawnie zainstalowana, posiada licencję i ma dostęp do niezbędnych zasobów systemowych. Wynik oceny pewności pomaga ustalić podstawowe oczekiwania dla konkretnych typów BarCode.

W przypadku wdrożeń produkcyjnych należy dokładnie zapoznać się z dokumentacją licencyjną. Licencje Enterprise umożliwiają nieograniczoną liczbę wdrożeń w ramach organizacji, co ma kluczowe znaczenie dla skalowania w wielu centrach danych. Przewodnik konfiguracji klucza licencyjnego wyjaśnia różne metody aktywacji, w tym zmienne środowiskowe i pliki konfiguracyjne dostosowane do Twoich praktyk DevOps.

Kompatybilność platform dla przedsiębiorstw

Twoja firma prawdopodobnie działa w środowisku heterogenicznym. Prace programistyczne odbywają się w systemie Windows, środowisko testowe działa w kontenerach Linux, a niektóre zespoły mogą korzystać z systemu macOS. Kompatybilność IronBarcode z różnymi platformami zapewnia spójne działanie na wszystkich tych platformach.

W przypadku wdrożeń kontenerowych przewodnik konfiguracji Docker zawiera szczegółowe instrukcje dotyczące kontenerów Linux. Obejmuje to obsługę zależności i optymalizację rozmiaru obrazów w celu wydajnego wdrożenia w chmurze. Jeśli wdrażasz rozwiązanie na platformie Azure lub AWS Lambda, przewodniki dotyczące konkretnych platform zapewnią optymalną wydajność w tych środowiskach.

Biblioteka obsługuje nawet scenariusze mobilne dzięki integracji z .NET MAUI, umożliwiając rozszerzenie możliwości skanowania kodów kreskowych na urządzenia z systemem iOS i Android, gdy pracownicy terenowi potrzebują funkcji skanowania mobilnego.

Jak zbudować kompletny kontroler API skanera?

Stwórzmy gotowe do użycia w środowisku produkcyjnym API skanera, które odpowiada rzeczywistym potrzebom Enterprise. To wdrożenie obejmuje odpowiednią obsługę błędów, kwestie bezpieczeństwa oraz optymalizację wydajności:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using IronBarCode;
using System.Drawing;
using System.ComponentModel.DataAnnotations;

namespace BarcodeScannerAPI.Controllers
{
    [ApiController]
    [Route("api/v1/[controller]")]
    [Authorize] // Require authentication for all endpoints
    public class ScannerController : ControllerBase
    {
        private readonly ILogger<ScannerController> _logger;
        private readonly IConfiguration _configuration;
        
        public ScannerController(ILogger<ScannerController> logger, IConfiguration configuration)
        {
            _logger = logger;
            _configuration = configuration;
        }
        
        // Enhanced result model with audit fields
        public class ScanResult
        {
            public bool Success { get; set; }
            public List<BarcodeData> Barcodes { get; set; } = new List<BarcodeData>();
            public string RequestId { get; set; } = Guid.NewGuid().ToString();
            public DateTime ProcessedAt { get; set; } = DateTime.UtcNow;
            public long ProcessingTimeMs { get; set; }
            public string ErrorMessage { get; set; }
            public Dictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>();
        }
        
        public class BarcodeData
        {
            public string Value { get; set; }
            public string Format { get; set; }
            public double Confidence { get; set; }
            public Rectangle Location { get; set; }
            public int PageNumber { get; set; } // For PDF processing
        }
        
        // Input validation model
        public class ScanRequest
        {
            [Required]
            public IFormFile File { get; set; }
            
            [Range(1, 10)]
            public int MaxBarcodes { get; set; } = 5;
            
            public string[] ExpectedFormats { get; set; }
            
            public bool EnableImageCorrection { get; set; } = true;
        }
        
        [HttpPost("scan")]
        [RequestSizeLimit(52428800)] // 50MB limit
        public async Task<ActionResult<ScanResult>> ScanDocument([FromForm] ScanRequest request)
        {
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();
            var result = new ScanResult();
            
            try
            {
                // Validate file type for security
                var allowedExtensions = new[] { ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".tiff", ".bmp" };
                var fileExtension = Path.GetExtension(request.File.FileName).ToLowerInvariant();
                
                if (!allowedExtensions.Contains(fileExtension))
                {
                    _logger.LogWarning($"Rejected file type: {fileExtension}");
                    return BadRequest(new ScanResult
                    {
                        Success = false,
                        ErrorMessage = "Unsupported file type. Allowed: PDF, PNG, JPG, GIF, TIFF, BMP"
                    });
                }
                
                // Process the file
                using var stream = new MemoryStream();
                await request.File.CopyToAsync(stream);
                var fileBytes = stream.ToArray();
                
                // Log for audit trail
                _logger.LogInformation($"Processing {request.File.FileName} ({fileBytes.Length} bytes) - RequestId: {result.RequestId}");
                
                // Configure scanner based on requirements
                var options = ConfigureOptions(request);
                
                // Handle different file types
                BarcodeResults scanResults;
                if (fileExtension == ".pdf")
                {
                    var pdfOptions = new PdfBarcodeReaderOptions
                    {
                        Scale = 3,
                        DPI = 300,
                        MaxThreads = 4
                    };
                    scanResults = BarcodeReader.ReadPdf(fileBytes, pdfOptions);
                }
                else
                {
                    scanResults = BarcodeReader.Read(fileBytes, options);
                }
                
                // Process results
                if (scanResults.Any())
                {
                    result.Success = true;
                    foreach (var barcode in scanResults.Take(request.MaxBarcodes))
                    {
                        result.Barcodes.Add(new BarcodeData
                        {
                            Value = barcode.Value,
                            Format = barcode.BarcodeType.ToString(),
                            Confidence = barcode.Confidence,
                            Location = barcode.Bounds,
                            PageNumber = barcode.PageNumber
                        });
                    }
                    
                    result.Metadata["TotalFound"] = scanResults.Count();
                    result.Metadata["FileSize"] = fileBytes.Length;
                    result.Metadata["FileName"] = request.File.FileName;
                    
                    _logger.LogInformation($"Successfully scanned {scanResults.Count()} barcodes - RequestId: {result.RequestId}");
                }
                else
                {
                    result.Success = false;
                    result.ErrorMessage = "No barcodes detected in the document";
                    _logger.LogWarning($"No barcodes found - RequestId: {result.RequestId}");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Scanning error - RequestId: {result.RequestId}");
                result.Success = false;
                result.ErrorMessage = "An error occurred during processing";
                
                // Don't expose internal errors to clients
                if (_configuration.GetValue<bool>("DetailedErrors"))
                {
                    result.Metadata["Exception"] = ex.Message;
                }
            }
            finally
            {
                stopwatch.Stop();
                result.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;
            }
            
            return result;
        }
        
        private BarcodeReaderOptions ConfigureOptions(ScanRequest request)
        {
            var options = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Balanced,
                ExpectMultipleBarcodes = request.MaxBarcodes > 1,
                RemoveFalsePositive = true,
                Multithreaded = true,
                MaxParallelThreads = Environment.ProcessorCount
            };
            
            // Apply format filtering if specified
            if (request.ExpectedFormats?.Any() == true)
            {
                var formats = BarcodeEncoding.None;
                foreach (var format in request.ExpectedFormats)
                {
                    if (Enum.TryParse<BarcodeEncoding>(format, true, out var encoding))
                    {
                        formats |= encoding;
                    }
                }
                options.ExpectBarcodeTypes = formats;
            }
            
            // Enable image correction for damaged barcodes
            if (request.EnableImageCorrection)
            {
                options.ImageFilters = new ImageFilterCollection
                {
                    new SharpenFilter(2),
                    new ContrastFilter(1.5f),
                    new BrightnessFilter(1.1f)
                };
                options.AutoRotate = true;
            }
            
            return options;
        }
        
        // Batch processing endpoint for high-volume scenarios
        [HttpPost("scan-batch")]
        [RequestSizeLimit(524288000)] // 500MB for batch operations
        public async Task<ActionResult<List<ScanResult>>> ScanBatch(List<IFormFile> files)
        {
            if (files == null || !files.Any())
            {
                return BadRequest("No files provided");
            }
            
            if (files.Count > 50)
            {
                return BadRequest("Maximum 50 files per batch");
            }
            
            var tasks = files.Select(file => ProcessFileAsync(file));
            var results = await Task.WhenAll(tasks);
            
            _logger.LogInformation($"Batch processed {files.Count} files, {results.Count(r => r.Success)} successful");
            
            return Ok(results);
        }
        
        private async Task<ScanResult> ProcessFileAsync(IFormFile file)
        {
            // Reuse the scanning logic
            var request = new ScanRequest 
            { 
                File = file,
                EnableImageCorrection = true 
            };
            var actionResult = await ScanDocument(request);
            
            if (actionResult.Result is OkObjectResult okResult)
            {
                return okResult.Value as ScanResult;
            }
            else if (actionResult.Result is BadRequestObjectResult badResult)
            {
                return badResult.Value as ScanResult;
            }
            
            return new ScanResult 
            { 
                Success = false, 
                ErrorMessage = "Processing failed" 
            };
        }
    }
}

To profesjonalne wdrożenie zawiera kilka kluczowych funkcji wymaganych w środowiskach produkcyjnych. Uwierzytelnianie gwarantuje, że dostęp do usługi skanowania mają wyłącznie uprawnieni użytkownicy. Ograniczenia rozmiaru żądań zapobiegają atakom typu denial-of-service. Kompletne logowanie zapewnia ścieżkę audytu, której potrzebują zespoły ds. zgodności.

Model odpowiedzi strukturalnej zwraca nie tylko wartości BarCode, ale także wskaźniki pewności i dane dotyczące lokalizacji. Te metadane są nieocenione w procesach zapewniania jakości. Gdy skanowanie BarCODE dostawcy ma niski poziom pewności, system może oznaczyć go do ręcznej weryfikacji.

Profesjonalne obsługiwanie błędów

Zauważyłeś, że kontroler nigdy nie ujawnia klientom szczegółów dotyczących wewnętrznych wyjątków? Jest to zgodne z najlepszymi praktykami w zakresie bezpieczeństwa, zapobiegając wyciekom informacji. Szczegółowe logowanie rejestruje wszystko, co jest potrzebne do debugowania, zachowując jednocześnie ogólny charakter odpowiedzi o błędach.

Pole RequestId umożliwia śledzenie end-to-end w Twoich rozproszonych systemach. Gdy pracownik magazynu zgłasza problem ze skanowaniem, zespół wsparcia technicznego może szybko zlokalizować konkretne zgłoszenie w scentralizowanym systemie rejestrowania zdarzeń. Znacznie skraca to średni czas rozwiązania (MTTR) problemów produkcyjnych.

Monitorowanie wydajności przez ProcessingTimeMs pomaga w identyfikacji wąskich gardeł. Jeśli przetwarzanie niektórych typów BarCodes konsekwentnie trwa dłużej, można odpowiednio dostosować ustawienia prędkości odczytu. Przykład dotyczący prędkości czytania pokazuje, jak różne ustawienia wpływają na wydajność.

Jak radzisz sobie z różnymi źródłami danych wejściowych?

Systemy Enterprise rzadko stosują jeden standardowy format. Twoje API skanera musi obsługiwać wszystko, od kamer magazynowych o wysokiej rozdzielczości po skany PDF niskiej jakości z faksów sprzed kilkudziesięciu lat. Oto jak zapewnić tę elastyczność:

// Extended controller with multiple input handlers
[ApiController]
[Route("api/v1/[controller]")]
[Authorize]
public class AdvancedScannerController : ControllerBase
{
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly ILogger<AdvancedScannerController> _logger;
    
    public AdvancedScannerController(
        IHttpClientFactory httpClientFactory, 
        ILogger<AdvancedScannerController> logger)
    {
        _httpClientFactory = httpClientFactory;
        _logger = logger;
    }
    
    // Handle Base64 input (common in web applications)
    [HttpPost("scan-base64")]
    public ActionResult<ScanResult> ScanBase64([FromBody] Base64Request request)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        
        try
        {
            // Validate Base64 format
            var base64Data = request.ImageData;
            if (base64Data.Contains(","))
            {
                // Handle data URL format: "data:image/png;base64,..."
                base64Data = base64Data.Substring(base64Data.IndexOf(",") + 1);
            }
            
            var imageBytes = Convert.FromBase64String(base64Data);
            
            // Implement size validation
            if (imageBytes.Length > 10 * 1024 * 1024) // 10MB limit
            {
                return BadRequest(new ScanResult
                {
                    Success = false,
                    ErrorMessage = "Image size exceeds 10MB limit"
                });
            }
            
            // Configure for web-uploaded images (often lower quality)
            var options = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Detailed,
                ImageFilters = new ImageFilterCollection
                {
                    new SharpenFilter(3),
                    new ContrastFilter(2),
                    new DeNoise()
                },
                TryInvertColor = true, // Handle inverted barcodes
                AutoRotate = true
            };
            
            var results = BarcodeReader.Read(imageBytes, options);
            return ProcessResults(results, "base64", request.FileName);
        }
        catch (FormatException)
        {
            return BadRequest(new ScanResult
            {
                Success = false,
                ErrorMessage = "Invalid Base64 format"
            });
        }
    }
    
    // Handle URL input (for cloud storage integration)
    [HttpPost("scan-url")]
    public async Task<ActionResult<ScanResult>> ScanFromUrl([FromBody] UrlScanRequest request)
    {
        if (!Uri.TryCreate(request.Url, UriKind.Absolute, out var uri))
        {
            return BadRequest(new ScanResult
            {
                Success = false,
                ErrorMessage = "Invalid URL format"
            });
        }
        
        // Validate URL domain (security measure)
        var allowedDomains = _configuration.GetSection("AllowedDomains").Get<string[]>() 
            ?? new[] { "blob.core.windows.net", "s3.amazonaws.com" };
        
        if (!allowedDomains.Any(domain => uri.Host.EndsWith(domain)))
        {
            _logger.LogWarning($"Rejected URL from unauthorized domain: {uri.Host}");
            return BadRequest(new ScanResult
            {
                Success = false,
                ErrorMessage = "URL domain not authorized"
            });
        }
        
        try
        {
            using var httpClient = _httpClientFactory.CreateClient("BarcodeScanner");
            httpClient.Timeout = TimeSpan.FromSeconds(30);
            
            // Add headers to avoid being blocked
            httpClient.DefaultRequestHeaders.Add("User-Agent", "BarcodeScannerAPI/2.0");
            
            var response = await httpClient.GetAsync(uri);
            response.EnsureSuccessStatusCode();
            
            // Check content type
            var contentType = response.Content.Headers.ContentType?.MediaType;
            if (!IsValidContentType(contentType))
            {
                return BadRequest(new ScanResult
                {
                    Success = false,
                    ErrorMessage = $"Unsupported content type: {contentType}"
                });
            }
            
            var imageBytes = await response.Content.ReadAsByteArrayAsync();
            
            // Use async processing for better scalability
            var results = await BarcodeReader.ReadAsync(imageBytes);
            return ProcessResults(results, "url", uri.ToString());
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, $"Failed to download from URL: {uri}");
            return BadRequest(new ScanResult
            {
                Success = false,
                ErrorMessage = "Failed to download image from URL"
            });
        }
        catch (TaskCanceledException)
        {
            return BadRequest(new ScanResult
            {
                Success = false,
                ErrorMessage = "Download timeout - file too large or slow connection"
            });
        }
    }
    
    // Handle multi-page PDFs with page-specific processing
    [HttpPost("scan-pdf-advanced")]
    public async Task<ActionResult<PdfScanResult>> ScanPdfAdvanced([FromForm] PdfScanRequest request)
    {
        using var stream = new MemoryStream();
        await request.File.CopyToAsync(stream);
        
        var pdfOptions = new PdfBarcodeReaderOptions
        {
            Scale = request.Scale ?? 3,
            DPI = request.DPI ?? 300,
            PageNumbers = request.PageNumbers,
            Password = request.Password,
            MaxThreads = Math.Min(request.MaxThreads ?? 4, Environment.ProcessorCount)
        };
        
        // For large PDFs, process in chunks
        if (stream.Length > 50 * 1024 * 1024) // 50MB
        {
            _logger.LogInformation($"Large PDF detected ({stream.Length / 1024 / 1024}MB), using chunked processing");
            pdfOptions.MaxThreads = 2; // Reduce memory pressure
        }
        
        var results = BarcodeReader.ReadPdf(stream.ToArray(), pdfOptions);
        
        // Group results by page
        var pageResults = results.GroupBy(r => r.PageNumber)
            .OrderBy(g => g.Key)
            .Select(g => new PageBarcodeResult
            {
                PageNumber = g.Key,
                BarcodeCount = g.Count(),
                Barcodes = g.Select(b => new BarcodeData
                {
                    Value = b.Value,
                    Format = b.BarcodeType.ToString(),
                    Confidence = b.Confidence,
                    Location = b.Bounds
                }).ToList()
            }).ToList();
        
        return Ok(new PdfScanResult
        {
            Success = true,
            TotalPages = pageResults.Count,
            TotalBarcodes = results.Count(),
            PageResults = pageResults,
            RequestId = Guid.NewGuid().ToString()
        });
    }
    
    // Handle damaged or low-quality barcodes
    [HttpPost("scan-damaged")]
    public async Task<ActionResult<ScanResult>> ScanDamagedBarcode([FromForm] IFormFile file)
    {
        using var stream = new MemoryStream();
        await file.CopyToAsync(stream);
        
        // Aggressive image correction for damaged barcodes
        var options = new BarcodeReaderOptions
        {
            Speed = ReadingSpeed.ExtremeDetail,
            ImageFilters = new ImageFilterCollection
            {
                new SharpenFilter(4),
                new ContrastFilter(3),
                new BrightnessFilter(1.5f),
                new BinaryThresholdFilter(128),
                new DeNoise(3)
            },
            TryInvertColor = true,
            AutoRotate = true,
            UseCode39ExtendedMode = true,
            RemoveFalsePositive = false, // Accept lower confidence
            Confidence = ConfidenceLevel.Low
        };
        
        var results = BarcodeReader.Read(stream.ToArray(), options);
        
        // If still no results, try with different threshold
        if (!results.Any())
        {
            options.ImageFilters = new ImageFilterCollection
            {
                new AdaptiveThresholdFilter(9),
                new MedianFilter(3),
                new Dilate(1)
            };
            
            results = BarcodeReader.Read(stream.ToArray(), options);
        }
        
        return ProcessResults(results, "damaged", file.FileName);
    }
    
    private bool IsValidContentType(string contentType)
    {
        var validTypes = new[]
        {
            "image/jpeg", "image/jpg", "image/png", "image/gif",
            "image/tiff", "image/bmp", "application/pdf"
        };
        return validTypes.Contains(contentType?.ToLower());
    }
    
    private ActionResult<ScanResult> ProcessResults(BarcodeResults results, string source, string identifier)
    {
        var scanResult = new ScanResult
        {
            Metadata = new Dictionary<string, object>
            {
                ["Source"] = source,
                ["Identifier"] = identifier,
                ["ProcessedAt"] = DateTime.UtcNow
            }
        };
        
        if (results.Any())
        {
            scanResult.Success = true;
            scanResult.Barcodes = results.Select(r => new BarcodeData
            {
                Value = r.Value,
                Format = r.BarcodeType.ToString(),
                Confidence = r.Confidence,
                Location = r.Bounds
            }).ToList();
            
            // Log low confidence results for quality monitoring
            var lowConfidence = results.Where(r => r.Confidence < 70).ToList();
            if (lowConfidence.Any())
            {
                _logger.LogWarning($"Low confidence barcodes detected: {lowConfidence.Count} of {results.Count()} from {identifier}");
            }
        }
        else
        {
            scanResult.Success = false;
            scanResult.ErrorMessage = "No barcodes detected";
        }
        
        return Ok(scanResult);
    }
}

// Request models
public class Base64Request
{
    [Required]
    public string ImageData { get; set; }
    public string FileName { get; set; }
}

public class UrlScanRequest
{
    [Required]
    [Url]
    public string Url { get; set; }
}

public class PdfScanRequest
{
    [Required]
    public IFormFile File { get; set; }
    public int? Scale { get; set; }
    public int? DPI { get; set; }
    public int[] PageNumbers { get; set; }
    public string Password { get; set; }
    public int? MaxThreads { get; set; }
}

// Response models
public class PdfScanResult : ScanResult
{
    public int TotalPages { get; set; }
    public int TotalBarcodes { get; set; }
    public List<PageBarcodeResult> PageResults { get; set; }
}

public class PageBarcodeResult
{
    public int PageNumber { get; set; }
    public int BarcodeCount { get; set; }
    public List<BarcodeData> Barcodes { get; set; }
}

To kompletne wdrożenie odpowiada rzeczywistym scenariuszom biznesowym w Enterprise. Punkt końcowy skanowania adresów URL obejmuje weryfikację domeny w celu zapobiegania atakom typu SSRF (server-side request forgery). Moduł obsługi Base64 usuwa prefiksy adresów URL danych, co jest powszechne podczas odbierania obrazów z aplikacji internetowych.

Uszkodzony punkt końcowy BarCode pokazuje możliwości IronBarcode w zakresie korekcji obrazu. Dzięki zastosowaniu wielu filtrów i wypróbowaniu różnych metod może odzyskać dane z poważnie uszkodzonych obrazów. Okazuje się to nieocenione w przypadku starych etykiet magazynowych lub dokumentów wysyłkowych zniszczonych przez warunki atmosferyczne.

Wybór między skanowaniem do formatu PDF a skanowaniem do formatu obrazu

Pliki PDF stwarzają wyjątkowe wyzwania i możliwości w zakresie skanowania BarCodes w Enterprise. Wiele dokumentów biznesowych, takich jak faktury, listy przewozowe i formularze zgodności, jest dostarczanych w formacie PDF z osadzonymi BARCODAMI. Funkcje odczytu kodów kreskowych w formacie PDF w IronBarcode elegancko radzą sobie z tymi scenariuszami.

Rozważmy typowy scenariusz w przedsiębiorstwie: dział księgowości otrzymuje co miesiąc tysiące faktur, z których każda zawiera kody kreskowe do automatycznego przetwarzania. Niektórzy dostawcy przesyłają pliki PDF wysokiej jakości, inni przesyłają zeskanowane dokumenty o różnej jakości.

Zaawansowany punkt końcowy skanowania plików PDF obsługuje oba scenariusze. W przypadku plików PDF o wysokiej jakości standardowe ustawienia sprawdzają się idealnie. W przypadku dokumentów zeskanowanych zwiększenie parametrów DPI i skali poprawia wskaźniki wykrywalności. Przetwarzanie poszczególnych stron umożliwia wyodrębnianie kodów kreskowych z określonych stron, co jest przydatne, gdy wiadomo, że faktury zawsze mają kody kreskowe na pierwszej stronie.

Wyniki pogrupowane według stron zapewniają cenny kontekst. Twój system przepływu pracy może kierować dokumenty w zależności od tego, które strony zawierają BARCODES, automatyzując klasyfikację dokumentów. To ustrukturyzowane podejście do przetwarzania dokumentów wielostronicowych przekształca procesy ręczne w wydajne, zautomatyzowane przepływy pracy.

Wydajna obsługa wielu BarCodes

Dokumenty Enterprise często zawierają wiele BARCODE-ów służących różnym celom. Etykieta wysyłkowa może zawierać BarCode do śledzenia przesyłki, BarCode produktu oraz BarCode miejsca docelowego. Właściwe obsłużenie wielu scenariuszy związanych z BarCodeami wymaga przemyślanego projektu API.

Punkt końcowy przetwarzania wsadowego pokazuje, jak efektywnie radzić sobie w sytuacjach wymagających przetwarzania dużych ilości danych. Przetwarzając wiele plików równolegle, można znacznie skrócić całkowity czas przetwarzania. Wzorzec Task.WhenAll zapewnia optymalne wykorzystanie zasobów przy jednoczesnym zachowaniu stabilności systemu.

Do tworzenia barcode'ów w aplikacjach IronBarcode oferuje równie skuteczne możliwości. Niezależnie od tego, czy potrzebujesz wygenerować liniowe BARCODE-y 1D dla systemów magazynowych, czy też stworzyć kody matrycowe 2D dla aplikacji mobilnych, stosuje się to samo proste podejście API.

Jak poprawić wydajność i dokładność?

Optymalizacja wydajności w skanowaniu BarCode w Enterprise to nie tylko kwestia szybkości — chodzi o znalezienie odpowiedniej równowagi dla konkretnego przypadku użycia. Poniższe przykłady przedstawiają zaawansowane techniki optymalizacji, które mogą zmienić wydajność skanowania:

public class OptimizedScannerService
{
    private readonly ILogger<OptimizedScannerService> _logger;
    private readonly IMemoryCache _cache;
    
    public OptimizedScannerService(ILogger<OptimizedScannerService> logger, IMemoryCache cache)
    {
        _logger = logger;
        _cache = cache;
    }
    
    // Performance-optimized scanning with caching
    public async Task<ScanResult> ScanWithOptimizationsAsync(byte[] imageData, string cacheKey = null)
    {
        // Check cache for repeat scans
        if (!string.IsNullOrEmpty(cacheKey))
        {
            if (_cache.TryGetValue(cacheKey, out ScanResult cachedResult))
            {
                _logger.LogInformation($"Cache hit for {cacheKey}");
                cachedResult.Metadata["CacheHit"] = true;
                return cachedResult;
            }
        }
        
        // Determine optimal settings based on image characteristics
        var settings = await DetermineOptimalSettingsAsync(imageData);
        
        // Apply region-specific scanning if applicable
        if (settings.UseRegionScanning)
        {
            return await ScanWithRegionsAsync(imageData, settings);
        }
        
        // Standard optimized scanning
        var results = await BarcodeReader.ReadAsync(imageData, settings.Options);
        var scanResult = BuildScanResult(results);
        
        // Cache successful results
        if (!string.IsNullOrEmpty(cacheKey) && scanResult.Success)
        {
            _cache.Set(cacheKey, scanResult, TimeSpan.FromMinutes(5));
        }
        
        return scanResult;
    }
    
    // Intelligent settings determination
    private async Task<ScanSettings> DetermineOptimalSettingsAsync(byte[] imageData)
    {
        var settings = new ScanSettings();
        
        // Quick analysis of image properties
        using var ms = new MemoryStream(imageData);
        using var image = Image.FromStream(ms);
        
        var width = image.Width;
        var height = image.Height;
        var aspectRatio = (double)width / height;
        
        _logger.LogInformation($"Image analysis: {width}x{height}, ratio: {aspectRatio:F2}");
        
        // High-resolution images can use faster scanning
        if (width > 2000 && height > 2000)
        {
            settings.Options.Speed = ReadingSpeed.Faster;
            settings.Options.ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128;
        }
        // Low-resolution needs more processing
        else if (width < 800 || height < 800)
        {
            settings.Options.Speed = ReadingSpeed.ExtremeDetail;
            settings.Options.ImageFilters = new ImageFilterCollection
            {
                new SharpenFilter(3),
                new ContrastFilter(2)
            };
        }
        else
        {
            settings.Options.Speed = ReadingSpeed.Balanced;
        }
        
        // Detect if image might contain multiple barcodes based on aspect ratio
        if (aspectRatio > 2 || aspectRatio < 0.5)
        {
            settings.Options.ExpectMultipleBarcodes = true;
            settings.UseRegionScanning = true;
        }
        
        // Enable rotation correction for potentially skewed images
        settings.Options.AutoRotate = true;
        
        return settings;
    }
    
    // Region-based scanning for large images
    private async Task<ScanResult> ScanWithRegionsAsync(byte[] imageData, ScanSettings settings)
    {
        var allResults = new List<BarcodeResult>();
        using var ms = new MemoryStream(imageData);
        using var image = Image.FromStream(ms);
        
        // Define scanning regions for common document layouts
        var regions = new[]
        {
            new Rectangle(0, 0, image.Width / 2, image.Height / 2), // Top-left
            new Rectangle(image.Width / 2, 0, image.Width / 2, image.Height / 2), // Top-right
            new Rectangle(0, image.Height / 2, image.Width / 2, image.Height / 2), // Bottom-left
            new Rectangle(image.Width / 2, image.Height / 2, image.Width / 2, image.Height / 2), // Bottom-right
            new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2) // Center
        };
        
        var tasks = regions.Select(async region =>
        {
            var regionOptions = new BarcodeReaderOptions
            {
                CropArea = region,
                Speed = ReadingSpeed.Faster,
                ExpectMultipleBarcodes = false
            };
            
            try
            {
                return await BarcodeReader.ReadAsync(imageData, regionOptions);
            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Region scan failed: {ex.Message}");
                return new BarcodeResult[0];
            }
        });
        
        var regionResults = await Task.WhenAll(tasks);
        
        // Combine and deduplicate results
        var uniqueResults = regionResults
            .SelectMany(r => r)
            .GroupBy(r => r.Value)
            .Select(g => g.OrderByDescending(r => r.Confidence).First())
            .ToList();
        
        return BuildScanResult(uniqueResults);
    }
    
    // Adaptive quality enhancement
    public async Task<ScanResult> ScanWithAdaptiveEnhancementAsync(byte[] imageData)
    {
        var attempts = new List<Func<Task<BarcodeResults>>>
        {
            // Attempt 1: Fast scan
            async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Faster,
                RemoveFalsePositive = true
            }),
            
            // Attempt 2: Standard scan with basic filters
            async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Balanced,
                ImageFilters = new ImageFilterCollection
                {
                    new ContrastFilter(1.5f),
                    new SharpenFilter(1)
                },
                TryInvertColor = true
            }),
            
            // Attempt 3: Detailed scan with aggressive filtering
            async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Detailed,
                ImageFilters = new ImageFilterCollection
                {
                    new AdaptiveThresholdFilter(11),
                    new DeNoise(2),
                    new MedianFilter(3)
                },
                AutoRotate = true,
                Confidence = ConfidenceLevel.Low
            }),
            
            // Attempt 4: Extreme processing for damaged barcodes
            async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.ExtremeDetail,
                ImageFilters = new ImageFilterCollection
                {
                    new BinaryThresholdFilter(100),
                    new Erode(1),
                    new Dilate(2),
                    new SharpenFilter(4)
                },
                RemoveFalsePositive = false,
                UseCode39ExtendedMode = true,
                TryInvertColor = true
            })
        };
        
        foreach (var (attempt, index) in attempts.Select((a, i) => (a, i)))
        {
            var stopwatch = Stopwatch.StartNew();
            var results = await attempt();
            stopwatch.Stop();
            
            _logger.LogInformation($"Attempt {index + 1} took {stopwatch.ElapsedMilliseconds}ms, found {results.Count()} barcodes");
            
            if (results.Any())
            {
                var scanResult = BuildScanResult(results);
                scanResult.Metadata["AttemptNumber"] = index + 1;
                scanResult.Metadata["ProcessingStrategy"] = GetStrategyName(index);
                return scanResult;
            }
        }
        
        return new ScanResult
        {
            Success = false,
            ErrorMessage = "No barcodes found after all enhancement attempts"
        };
    }
    
    // Machine learning confidence optimization
    public class MLOptimizedScanner
    {
        private readonly Dictionary<string, double> _formatConfidenceThresholds = new()
        {
            { "QRCode", 85.0 },
            { "Code128", 90.0 },
            { "Code39", 88.0 },
            { "DataMatrix", 87.0 },
            { "EAN13", 92.0 },
            { "PDF417", 86.0 }
        };
        
        public async Task<ScanResult> ScanWithMLConfidenceAsync(byte[] imageData, string expectedFormat = null)
        {
            var options = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Balanced,
                Confidence = ConfidenceLevel.Optional
            };
            
            // If we know the expected format, improve for it
            if (!string.IsNullOrEmpty(expectedFormat) && 
                Enum.TryParse<BarcodeEncoding>(expectedFormat, out var encoding))
            {
                options.ExpectBarcodeTypes = encoding;
            }
            
            var results = await BarcodeReader.ReadAsync(imageData, options);
            
            // Apply ML confidence filtering
            var confidenceThreshold = expectedFormat != null && 
                _formatConfidenceThresholds.ContainsKey(expectedFormat)
                ? _formatConfidenceThresholds[expectedFormat]
                : 80.0;
            
            var highConfidenceResults = results
                .Where(r => r.Confidence >= confidenceThreshold)
                .ToList();
            
            if (highConfidenceResults.Any())
            {
                return BuildScanResult(highConfidenceResults);
            }
            
            // If no high-confidence results, include lower confidence with warnings
            var lowConfidenceResults = results
                .Where(r => r.Confidence < confidenceThreshold)
                .ToList();
            
            if (lowConfidenceResults.Any())
            {
                var result = BuildScanResult(lowConfidenceResults);
                result.Metadata["Warning"] = "Low confidence results - manual verification recommended";
                result.Metadata["MinConfidence"] = lowConfidenceResults.Min(r => r.Confidence);
                return result;
            }
            
            return new ScanResult
            {
                Success = false,
                ErrorMessage = "No barcodes met confidence threshold"
            };
        }
    }
    
    private ScanResult BuildScanResult(IEnumerable<BarcodeResult> results)
    {
        var resultList = results.ToList();
        return new ScanResult
        {
            Success = true,
            Barcodes = resultList.Select(r => new BarcodeData
            {
                Value = r.Value,
                Format = r.BarcodeType.ToString(),
                Confidence = r.Confidence,
                Location = r.Bounds
            }).ToList(),
            Metadata = new Dictionary<string, object>
            {
                ["TotalFound"] = resultList.Count,
                ["AverageConfidence"] = resultList.Average(r => r.Confidence),
                ["Formats"] = resultList.Select(r => r.BarcodeType.ToString()).Distinct().ToArray()
            }
        };
    }
    
    private string GetStrategyName(int attemptIndex)
    {
        return attemptIndex switch
        {
            0 => "FastScan",
            1 => "StandardEnhanced",
            2 => "DetailedFiltering",
            3 => "ExtremeDamageRecovery",
            _ => "Unknown"
        };
    }
}

// Supporting classes
public class ScanSettings
{
    public BarcodeReaderOptions Options { get; set; } = new BarcodeReaderOptions();
    public bool UseRegionScanning { get; set; }
    public List<Rectangle> CustomRegions { get; set; }
}

// Benchmark service for performance testing
public class BenchmarkService
{
    private readonly ILogger<BenchmarkService> _logger;
    
    public async Task<BenchmarkResult> BenchmarkSettingsAsync(byte[] testImage, int iterations = 10)
    {
        var results = new Dictionary<string, BenchmarkData>();
        
        var testConfigurations = new Dictionary<string, BarcodeReaderOptions>
        {
            ["Fastest"] = new() { Speed = ReadingSpeed.Faster },
            ["Balanced"] = new() { Speed = ReadingSpeed.Balanced },
            ["Detailed"] = new() { Speed = ReadingSpeed.Detailed },
            ["Parallel"] = new() { Speed = ReadingSpeed.Balanced, Multithreaded = true, MaxParallelThreads = 4 },
            ["Filtered"] = new() 
            { 
                Speed = ReadingSpeed.Balanced, 
                ImageFilters = new ImageFilterCollection { new SharpenFilter(2), new ContrastFilter(1.5f) } 
            }
        };
        
        foreach (var config in testConfigurations)
        {
            var times = new List<long>();
            var successCount = 0;
            
            for (int i = 0; i < iterations; i++)
            {
                var sw = Stopwatch.StartNew();
                var scanResults = await BarcodeReader.ReadAsync(testImage, config.Value);
                sw.Stop();
                
                times.Add(sw.ElapsedMilliseconds);
                if (scanResults.Any()) successCount++;
                
                // Small delay between tests
                await Task.Delay(100);
            }
            
            results[config.Key] = new BenchmarkData
            {
                AverageMs = times.Average(),
                MinMs = times.Min(),
                MaxMs = times.Max(),
                SuccessRate = (double)successCount / iterations * 100
            };
        }
        
        return new BenchmarkResult { Results = results };
    }
}

public class BenchmarkData
{
    public double AverageMs { get; set; }
    public long MinMs { get; set; }
    public long MaxMs { get; set; }
    public double SuccessRate { get; set; }
}

public class BenchmarkResult
{
    public Dictionary<string, BenchmarkData> Results { get; set; }
}

To zaawansowane podejście do optymalizacji wykorzystuje kilka profesjonalnych technik. Inteligentne ustalanie ustawień analizuje właściwości obrazu, aby automatycznie wybrać optymalne parametry przetwarzania. Obrazy o wysokiej rozdzielczości z nowoczesnych aparatów mogą być przetwarzane szybciej, podczas gdy skany o niskiej jakości są poddawane ulepszonemu filtrowaniu.

Skanowanie oparte na regionach okazuje się szczególnie skuteczne w przypadku dokumentów wielkoformatowych. Dzięki podziałowi obrazu na regiony i równoległemu przetwarzaniu można osiągnąć znaczną poprawę wydajności. Technika ta sprawdza się szczególnie dobrze w przypadku standardowych formularzy, w których lokalizacja kodów BarCode jest przewidywalna.

Wybieranie odpowiedniego ustawienia ReadingSpeed

Podejście oparte na adaptacyjnym ulepszaniu polega na stopniowym stosowaniu coraz bardziej agresywnych technik przetwarzania, aż do osiągnięcia sukcesu. Zapewnia to najszybsze możliwe przetwarzanie BarCodes dobrej jakości, przy jednoczesnym skutecznym radzeniu sobie z BarCodes uszkodzonymi. Funkcja progu pewności wykorzystuje uczenie maszynowe do weryfikacji wyników, co zmniejsza liczbę fałszywych alarmów w środowiskach produkcyjnych.

W przypadku konkretnych scenariuszy optymalizacji poniższa tabela przedstawia powiązania między typowymi przypadkami użycia a zalecanymi ustawieniami:

Ustawienia prędkości czytania według przypadku użycia
Przykład zastosowaniaZalecana prędkośćOpcje dodatkoweOczekiwany kompromis
Przetwarzanie wsadowe dużych ilości danychSzybciejFiltruj według oczekiwanego typu BarCodeNajszybsza przepustowość; może pomijać uszkodzone BarCodes
Dokumenty o zróżnicowanej jakościZrównoważonyAdaptacyjne ulepszenie rezerwoweDobra równowaga między szybkością a dokładnością
Uszkodzone lub zniszczone BarCodesExtremeDetailPełny potok filtrów obrazuNajwyższa dokładność; mniejsza wydajność
Punkty końcowe API działające w czasie rzeczywistymZrównoważonyBuforowanie + skanowanie regionuStały czas odpowiedzi poniżej 200 ms
Pobieranie faktur w formacie PDFZrównoważonyDPI 300, skala 3Najlepsze rozwiązanie dla plików PDF z warstwą tekstową

Usługa benchmarkowa pomaga podejmować decyzje dotyczące konfiguracji w oparciu o dane. Przeprowadź testy porównawcze z rzeczywistymi próbkami BarCode'ów, aby znaleźć optymalną równowagę między szybkością a dokładnością dla konkretnego przypadku użycia. Wytyczne branżowe zawarte w najlepszych praktykach Microsoftu dotyczących wydajności .NET Core mają również bezpośrednie zastosowanie podczas dostosowywania punktów końcowych API skanera.

Wpływ filtrów obrazu

Filtry obrazu mogą znacznie poprawić wskaźniki rozpoznawalności trudnych BARCODE-ów. Dokumentacja dotycząca korekcji obrazu wyjaśnia przeznaczenie każdego filtra. Filtry wydłużają jednak czas przetwarzania, dlatego należy z nich korzystać rozważnie.

W przypadku wdrożeń Enterprise warto rozważyć podejście warstwowe:

  1. Szybki przegląd bez filtrów w ramach wstępnej próby
  2. Zastosuj podstawowe filtry, jeśli pierwsza próba się nie powiedzie
  3. Stosuj agresywne filtrowanie tylko wtedy, gdy jest to konieczne
  4. Buforuj wyniki, aby uniknąć ponownego przetwarzania

Strategia ta pozwala zachować szybki średni czas odpowiedzi, a jednocześnie skutecznie radzić sobie z trudnymi przypadkami. Funkcja korekcji orientacji okazuje się szczególnie przydatna w przypadku zdjęć wykonanych telefonem, gdzie użytkownicy mogą trzymać urządzenia pod różnymi kątami.

Jak generować obrazy kodów QR w języku C#?

Chociaż skanowanie ma kluczowe znaczenie, wiele aplikacji Enterprise wymaga również generowania BARCODE-ów. IronBarcode sprawia, że tworzenie kodów jest tak proste, jak ich odczytywanie. Oto jak generować kody QR dla różnych scenariuszy Enterprise:

public class BarcodeGenerationService
{
    private readonly ILogger<BarcodeGenerationService> _logger;
    
    // Generate QR codes for asset tracking
    public byte[] GenerateAssetQRCode(AssetInfo asset)
    {
        // Create JSON payload with asset information
        var assetData = JsonSerializer.Serialize(new
        {
            Id = asset.AssetId,
            Type = asset.AssetType,
            Location = asset.CurrentLocation,
            LastMaintenance = asset.LastMaintenanceDate,
            Url = "___PROTECTED_URL_45___"
        });
        
        // Generate QR code with high error correction for durability
        var qrCode = QRCodeWriter.CreateQrCode(assetData, 500, QRCodeWriter.QrErrorCorrectionLevel.High);
        
        // Add company branding
        qrCode.AddAnnotationTextAboveBarcode($"ASSET: {asset.AssetId}");
        qrCode.AddAnnotationTextBelowBarcode(asset.AssetType);
        qrCode.SetMargins(10);
        
        // Style for printing on asset labels
        qrCode.ChangeBarCodeColor(Color.Black);
        qrCode.ChangeBackgroundColor(Color.White);
        
        return qrCode.ToStream().ToArray();
    }
    
    // Generate visitor badges with QR codes
    public GeneratedBarcode CreateVisitorBadgeQR(VisitorInfo visitor)
    {
        // Encode visitor information with expiration
        var visitorData = new
        {
            Name = visitor.Name,
            Company = visitor.Company,
            Host = visitor.HostEmployee,
            ValidFrom = visitor.CheckInTime,
            ValidUntil = visitor.CheckInTime.AddHours(8),
            AccessLevel = visitor.AccessLevel,
            BadgeId = Guid.NewGuid().ToString()
        };
        
        var qrCode = QRCodeWriter.CreateQrCode(
            JsonSerializer.Serialize(visitorData), 
            400, 
            QRCodeWriter.QrErrorCorrectionLevel.Medium
        );
        
        // Add company logo for professional appearance
        if (File.Exists("company-logo.png"))
        {
            qrCode.AddLogo("company-logo.png");
        }
        
        // Style for badge printing
        qrCode.SetMargins(15);
        qrCode.ChangeBarCodeColor(Color.FromArgb(0, 48, 135)); // Company blue
        
        // Add visible text for security personnel
        qrCode.AddAnnotationTextAboveBarcode($"VISITOR: {visitor.Name}");
        qrCode.AddAnnotationTextBelowBarcode($"Expires: {visitor.CheckInTime.AddHours(8):HH:mm}");
        
        _logger.LogInformation($"Generated visitor badge for {visitor.Name}, BadgeId: {visitorData.BadgeId}");
        
        return qrCode;
    }
    
    // Generate shipping labels with multiple barcodes
    public byte[] GenerateShippingLabel(ShippingInfo shipping)
    {
        // Create a PDF with multiple barcodes
        var pdf = new IronPdf.ChromePdfRenderer();
        
        // Generate tracking barcode (Code 128 for USPS/UPS compatibility)
        var trackingBarcode = BarcodeWriter.CreateBarcode(
            shipping.TrackingNumber, 
            BarcodeEncoding.Code128
        );
        trackingBarcode.ResizeTo(300, 75);
        trackingBarcode.SetMargins(5);
        
        // Generate postal code barcode
        var postalBarcode = BarcodeWriter.CreateBarcode(
            shipping.PostalCode,
            BarcodeEncoding.Code128
        );
        postalBarcode.ResizeTo(200, 50);
        
        // Generate QR code with complete shipping data
        var shippingData = JsonSerializer.Serialize(shipping);
        var qrCode = QRCodeWriter.CreateQrCode(shippingData, 200);
        
        // Combine into shipping label HTML
        var labelHtml = $@
        <html>
        <body style='font-family: Arial, sans-serif;'>
            <div style='border: 2px solid black; padding: 20px; width: 4in; height: 6in;'>
                <h2>SHIPPING LABEL</h2>
                <hr/>
                <p><strong>From:</strong><br/>{shipping.SenderAddress}</p>
                <p><strong>To:</strong><br/>{shipping.RecipientAddress}</p>
                <hr/>
                <div style='text-align: center;'>
                    <img src='{trackingBarcode.ToDataUrl()}' alt='Tracking barcode'/>
                    <p>Tracking: {shipping.TrackingNumber}</p>
                </div>
                <div style='margin-top: 20px;'>
                    <img src='{postalBarcode.ToDataUrl()}' alt='Postal barcode' style='float: left;'/>
                    <img src='{qrCode.ToDataUrl()}' alt='Shipping QR code' style='float: right; width: 100px;'/>
                </div>
                <div style='clear: both; margin-top: 20px; font-size: 10px;'>
                    <p>Service: {shipping.ServiceType} | Weight: {shipping.Weight}lbs</p>
                </div>
            </div>
        </body>
        </html>";
        
        return pdf.RenderHtmlAsPdf(labelHtml).BinaryData;
    }
    
    // Generate secure document QR codes with encryption
    public class SecureDocumentQR
    {
        private readonly byte[] _encryptionKey;
        
        public SecureDocumentQR(byte[] encryptionKey)
        {
            _encryptionKey = encryptionKey;
        }
        
        public GeneratedBarcode GenerateSecureDocumentQR(DocumentInfo document)
        {
            // Create document reference with security features
            var documentRef = new
            {
                DocumentId = document.Id,
                Type = document.DocumentType,
                CreatedDate = document.CreatedDate,
                Hash = ComputeDocumentHash(document),
                AccessUrl = "___PROTECTED_URL_46___",
                ValidUntil = DateTime.UtcNow.AddDays(30)
            };
            
            // Encrypt sensitive data
            var jsonData = JsonSerializer.Serialize(documentRef);
            var encryptedData = EncryptData(jsonData);
            
            // Generate QR with encrypted payload
            var qrCode = QRCodeWriter.CreateQrCode(
                Convert.ToBase64String(encryptedData),
                500,
                QRCodeWriter.QrErrorCorrectionLevel.High
            );
            
            // Add visual security indicators
            qrCode.ChangeBarCodeColor(Color.DarkGreen);
            qrCode.AddAnnotationTextAboveBarcode("SECURE DOCUMENT");
            qrCode.AddAnnotationTextBelowBarcode($"Expires: {documentRef.ValidUntil:yyyy-MM-dd}");
            
            return qrCode;
        }
        
        private string ComputeDocumentHash(DocumentInfo document)
        {
            using var sha256 = SHA256.Create();
            var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(document.Content ?? document.Id));
            return BitConverter.ToString(hash).Replace("-", "");
        }
        
        private byte[] EncryptData(string data)
        {
            // Simplified encryption - use proper encryption in production
            using var aes = Aes.Create();
            aes.Key = _encryptionKey;
            aes.GenerateIV();
            
            using var encryptor = aes.CreateEncryptor();
            var dataBytes = Encoding.UTF8.GetBytes(data);
            var encrypted = encryptor.TransformFinalBlock(dataBytes, 0, dataBytes.Length);
            
            // Prepend IV for decryption
            return aes.IV.Concat(encrypted).ToArray();
        }
    }
    
    // Batch generation for high-volume scenarios
    public async Task<List<GeneratedBarcode>> GenerateBatchQRCodesAsync(List<string> data, QRCodeOptions options)
    {
        var tasks = data.Select(item => Task.Run(() =>
        {
            var qr = QRCodeWriter.CreateQrCode(
                item, 
                options.Size, 
                options.ErrorCorrection
            );
            
            if (options.IncludeMargins)
                qr.SetMargins(options.MarginSize);
                
            if (options.CustomColor.HasValue)
                qr.ChangeBarCodeColor(options.CustomColor.Value);
                
            return qr;
        }));
        
        return (await Task.WhenAll(tasks)).ToList();
    }
}

// Supporting models
public class AssetInfo
{
    public string AssetId { get; set; }
    public string AssetType { get; set; }
    public string CurrentLocation { get; set; }
    public DateTime LastMaintenanceDate { get; set; }
}

public class VisitorInfo
{
    public string Name { get; set; }
    public string Company { get; set; }
    public string HostEmployee { get; set; }
    public DateTime CheckInTime { get; set; }
    public string AccessLevel { get; set; }
}

public class ShippingInfo
{
    public string TrackingNumber { get; set; }
    public string SenderAddress { get; set; }
    public string RecipientAddress { get; set; }
    public string PostalCode { get; set; }
    public string ServiceType { get; set; }
    public decimal Weight { get; set; }
}

public class DocumentInfo
{
    public string Id { get; set; }
    public string DocumentType { get; set; }
    public DateTime CreatedDate { get; set; }
    public string Content { get; set; }
}

public class QRCodeOptions
{
    public int Size { get; set; } = 400;
    public QRCodeWriter.QrErrorCorrectionLevel ErrorCorrection { get; set; } = QRCodeWriter.QrErrorCorrectionLevel.Medium;
    public bool IncludeMargins { get; set; } = true;
    public int MarginSize { get; set; } = 10;
    public Color? CustomColor { get; set; }
}

Te przykłady generowania pokazują przypadki użycia specyficzne dla Enterprise. Kody QR służące do śledzenia zasobów zawierają historię konserwacji oraz bezpośrednie linki do systemów zarządzania zasobami. Identyfikatory gości zawierają daty ważności i poziomy dostępu w celu zapewnienia zgodności z wymogąmi bezpieczeństwa. Etykiety wysyłkowe łączą wiele formatów BARCODE-ów, aby spełnić wymagania przewoźników.

Wdrożenie bezpiecznego dokumentu QR pokazuje, jak zintegrować szyfrowanie danych wrażliwych. Takie podejście gwarantuje, że nawet jeśli ktoś zeskanuje kod QR, nie będzie mógł uzyskać dostępu do informacji bez odpowiednich kluczy deszyfrujących. Ma to kluczowe znaczenie w przypadku dokumentów dotyczących zgodności, dokumentacji finansowej lub poufnej korespondencji.

Jakie są Twoje kolejne kroki?

Stworzenie korporacyjnego interfejsu API skanera kodów kreskowych za pomocą IronBarcode zapewnia solidną podstawę dla inicjatyw transformacji cyfrowej. Połączenie pełnej obsługi formatów, zaawansowanego przetwarzania obrazów i kompatybilności międzyplatformowej pozwala sprostać złożonym wymaganiom współczesnych Enterprise. Przed sfinalizowaniem architektury warto zapoznać się z dokumentacją standardów BarCode GS1, aby zrozumieć wymagania dotyczące kodowania BarCode stosowanych w łańcuchu dostaw i handlu detalicznym. W przypadku wzorców projektowych REST API użytych w powyższych przykładach kontrolerów praktycznym źródłem informacji jest przewodnik RESTful API Design dostępny na stronie restfulapi.net. W przypadku wdrażania w środowiskach kontenerowych oficjalna dokumentacja Docker dotycząca obrazów .NET stanowi autorytatywne źródło informacji przy wyborze obrazu bazowego.

Najważniejsze wskazówki dotyczące wdrożenia:

  1. Bezpieczeństwo przede wszystkim: od samego początku wdrażaj odpowiednie uwierzytelnianie, walidację danych wejściowych i rejestrowanie audytowe
  2. Optymalizacja wydajności: Należy stosować odpowiednie prędkości skanowania i strategie buforowania dostosowane do konkretnego przypadku użycia
  3. Obsługa błędów: Twórz odporne systemy, które płynnie radzą sobie z sytuacjami skrajnymi i zapewniają konstruktywne informacje zwrotne
  4. Skalowalność: Projektuj z myślą o skalowaniu horyzontalnym, wykorzystując wzorce asynchroniczne i efektywne zarządzanie zasobami

W przypadku wdrożeń produkcyjnych warto rozważyć następujące dodatkowe zasoby:

Funkcje IronBarcode dla Enterprise wykraczają poza podstawowe skanowanie. Możliwości dostosowywania stylu biblioteki umożliwiają generowanie BARCODE'ów z logo marki. Obsługa kodów kreskowych Unicode zapewnia globalną kompatybilność. Zaawansowane funkcje, takie jak marginesy BarCode i poziomy korekcji błędów, zapewniają precyzyjną kontrolę nad jakością wydruku.

Wsparcie i zasoby dla Enterprise

Podczas wdrażania rozwiązań do obsługi kodów kreskowych o znaczeniu krytycznym ważne jest posiadanie niezawodnego wsparcia. IronBarcode oferuje:

Przejście od ręcznej obsługi BarCodes do zautomatyzowanego przetwarzania opartego na API zmienia wydajność operacyjną. Niezależnie od tego, czy przetwarzasz tysiące dokumentów wysyłkowych, zarządzasz dostępem gości, czy śledzisz zasoby przedsiębiorstwa, IronBarcode zapewnia niezawodność i funkcje wymagane w środowiskach Enterprise.

Chcesz zrewolucjonizować przetwarzanie kodów kreskowych? Zacznij od bezpłatnej wersji próbnej i przekonaj się, jaką różnicę może zapewnić profesjonalne przetwarzanie kodów kreskowych. Pełna dokumentacja API zawiera szczegółowe wskazówki dotyczące wdrażania, a sekcja przykładów oferuje gotowy do użycia kod dla typowych scenariuszy.

Twoja firma zasługuje na rozwiązanie do obsługi BARCODE, które skaluje się wraz z Twoimi potrzebami, zapewnia zgodność z wymogąmi bezpieczeństwa i dostarcza spójne wyniki na wszystkich platformach. IronBarcode zapewnia właśnie to — wspierany przez firmę zaangażowaną w długoterminowe wsparcie i ciągłe doskonalenie. Zacznij tworzyć swoje API skanera już dziś i dołącz do tysięcy przedsiębiorstw, które zaufały IronBarcode w zakresie swoich kluczowych potrzeb związanych z przetwarzaniem kodów kreskowych.

Curtis Chau
Autor tekstów technicznych

Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podręczników.

...
Czytaj więcej

Powiązane artykuły

Key in blue circle

Uzyskaj natychmiast swój darmowy 30-dniowy Klucz Testowy.

Your trial license will be sent to your email address

Brak ograniczeń. 100% dostępności. Bez karty kredytowej.

bullet_checkedNie wymaga karty kredytowej ani tworzenia kontaBrak ograniczeń. 100% dostępności. Bez karty kredytowej.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Zarezerwuj swoje darmowe Demo na żywo
Booking Badge

Zaufane przez miliony inżynierów na całym świecie

Logotypy klientów Iron Software
Otrzymaj swoje Konsultacja Bez Zobowiązań
Wypełnij poniższy formularz lub wyślij e-mail na sales@ironsoftware.com
Twoje dane zawsze będą utrzymywane w tajemnicy.
Zaufane przez miliony inżynierów na całym świecie
Logotypy klientów Iron Software
Otrzymaj swój darmowy Klucz Próbny na 30 dni natychmiast.
Nie wymaga karty kredytowej ani tworzenia konta