使用IRONBARCODE

如何创建一个Blazor二维码扫描器

发布 2024年二月18日
分享:

简介

本文探讨了快速反应代码扫描仪的集成问题 (QR 码扫描器) 在 Blazor 应用程序中使用 IronQR(一个 .NET 库)。QR 码是一种二维条形码,与普通的一维条形码相比,它能存储更多的数据。

微软的一个框架 Blazor 允许开发人员制作单页应用程序 (使用 Blazor WebAssembly 应用程序) 或使用 C# 来构建交互式网络界面、 (本指南将重点介绍 Blazor 服务器).

IronQR 与 Blazor 服务器在二维码扫描方面的集成是一项战略性组合,充分利用了两种技术的优势。通过将 IronQR 与 Blazor 应用程序集成,您可以高效地处理二维码的生成和扫描。二维码阅读器的这一功能在库存管理、票务系统和非接触式信息共享等各种业务环境中的需求日益增长。

了解基础知识

什么是 Blazor 服务器?

Blazor 服务器 是一个网络应用程序框架,是 ASP.NET Core 平台的一部分。它使开发人员能够使用 C# 而不是 JavaScript 构建交互式网络用户界面。这种服务器端模型通过 SignalR 连接(一种实时网络功能)处理用户交互。这有助于开发人员创建有效的交互式网络应用程序。

IronQR 简介

IronQR 是一个.NET 库,它的突出特点是能够读取、解释并 生成二维码 准确度极高。它提供一系列功能,包括处理不同类型 QR 码内容的能力。IronQR 的优势在于简单易用,易于集成到.NET 应用程序中,是希望集成和创建 QR 码功能的开发人员的首选。

如何创建 Blazor QR 码扫描器

1.在 Visual Studio Code 中创建 Blazor 服务器应用程序

2.使用 NuGet 包管理器安装 QR 代码类库

3.在 index.razor 中使用 HTML 和 CSS 创建用户界面

4.编写上传文件处理逻辑

5.使用 QR 库编写 QR 扫描逻辑

6.在文本框中显示结果

设置环境

创建新的Blazor服务器应用程序

启动 Visual Studio 并选择 "创建新项目"。在项目模板选择界面,找到并选择 "Blazor Server App "模板。单击 "下一步"。

如何创建 Blazor QR 码扫描器:图 1 - 找到正确的实施模板

选择模板后,输入项目名称和地点 (其他一切保持默认值) 然后点击 "下一步 "按钮。

如何创建 Blazor QR 码扫描器:图 2 - 配置项目详情

现在选择所需的 .NET Framework,然后点击创建按钮。它将创建一个 Blazor 服务器应用程序。

如何创建 Blazor QR 码扫描器:图 3 - 选择 .NET 框架并创建项目

安装 IronQR 库

点击菜单栏中的 "工具"。从下拉菜单中选择 "NuGet 包管理器"。从上下文菜单中选择 "管理解决方案的 NuGet 包"。这将打开 NuGet 包管理器选项卡。

如何创建 Blazor QR 码扫描器:图 4 - 访问 NuGet 软件包管理器

在 NuGet 软件包管理器中,在 "浏览 "选项卡中搜索 "IronQR"。然后在列表中找到 "IronQR "软件包。点击 "安装 "按钮。

如何创建 Blazor QR 码扫描器:图 5 - 通过 浏览 选项卡安装 IronQR 软件包

现在一切都已安装完毕,我们可以了解一下项目结构以及如何在项目中实施一切。

实施 QR 码扫描

构建用户界面

二维码扫描器的用户界面主要是在Index.razor文件中构建的。该文件是 Blazor 服务器项目的一部分,结合使用 HTML 和 Razor 语法创建动态交互式网页。其结构包括

@page "/"
@using System.IO
@using Microsoft.AspNetCore.Components.Forms
@using IronQr
@using IronSoftware.Drawing
@inject IJSRuntime JSRuntime
<PageTitle>QR Code Scanner</PageTitle>
<div>
    <h1>QR Code Scanner</h1> 
    <InputFile OnChange="HandleSelectedFile" accept="image/*" class="file-input" />
    @if (!string.IsNullOrEmpty(qrImageSrc))
    {
        <img src="@qrImageSrcForDisplay" alt="QR Code Image" class="qr-image" />
    }
    <button @onclick="ScanQRCode" disabled="@(!fileSelected)" class="button scan-button">Scan QR Code</button>
    @if (!string.IsNullOrEmpty(scannedText))
    {
        <div class="result-section">
            <button @onclick="CopyToClipboard" class="button copy-button">Copy</button>
        </div>
    }
</div>
@page "/"
@using System.IO
@using Microsoft.AspNetCore.Components.Forms
@using IronQr
@using IronSoftware.Drawing
@inject IJSRuntime JSRuntime
<PageTitle>QR Code Scanner</PageTitle>
<div>
    <h1>QR Code Scanner</h1> 
    <InputFile OnChange="HandleSelectedFile" accept="image/*" class="file-input" />
    @if (!string.IsNullOrEmpty(qrImageSrc))
    {
        <img src="@qrImageSrcForDisplay" alt="QR Code Image" class="qr-image" />
    }
    <button @onclick="ScanQRCode" disabled="@(!fileSelected)" class="button scan-button">Scan QR Code</button>
    @if (!string.IsNullOrEmpty(scannedText))
    {
        <div class="result-section">
            <button @onclick="CopyToClipboard" class="button copy-button">Copy</button>
        </div>
    }
</div>
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: @page "/" using System.IO using Microsoft.AspNetCore.Components.Forms using IronQr using IronSoftware.Drawing inject IJSRuntime JSRuntime <PageTitle> QR Code Scanner</PageTitle> <div> <h1> QR Code Scanner</h1> <InputFile OnChange="HandleSelectedFile" accept="image/*" class="file-input" /> if(!string.IsNullOrEmpty(qrImageSrc))
"image/*" Class="file-input" /> [if](Not String.IsNullOrEmpty(qrImageSrc))
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: Friend @page "/" using System.IO using Microsoft.AspNetCore.Components.Forms using IronQr using IronSoftware.Drawing inject IJSRuntime JSRuntime <PageTitle> QR Code Scanner</PageTitle> <div> <h1> QR Code Scanner</h1> <InputFile OnChange="HandleSelectedFile" accept="image/*" Class
"HandleSelectedFile" accept="image/*" Class
Friend page "/" [using] System.IO [using] Microsoft.AspNetCore.Components.Forms [using] IronQr [using] IronSoftware.Drawing inject IJSRuntime JSRuntime (Of PageTitle) QR Code Scanner</PageTitle> (Of div) (Of h1) QR Code Scanner</h1> <InputFile OnChange="HandleSelectedFile" accept
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: <img src="@qrImageSrcForDisplay" alt="QR Code Image" class="qr-image" />
		"QR Code Image" class="qr-image" />
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: <img src="@qrImageSrcForDisplay" alt="QR Code Image" class
		"@qrImageSrcForDisplay" alt="QR Code Image" class
		<img src="@qrImageSrcForDisplay" alt
End Class
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: <button onclick="ScanQRCode" disabled="@(!fileSelected)" class="button scan-button"> Scan QR Code</button> if(!string.IsNullOrEmpty(scannedText))
	"@(!fileSelected)" class="button scan-button"> Scan QR Code</button> [if](Not String.IsNullOrEmpty(scannedText))
	If True Then
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: <button onclick="ScanQRCode" disabled="@(!fileSelected)" class
	"ScanQRCode" disabled="@(!fileSelected)" class
	<button onclick="ScanQRCode" disabled
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: <div class="result-section"> <button onclick="CopyToClipboard" class="button copy-button"> Copy</button> </div>
		"CopyToClipboard" class="button copy-button"> Copy</button> </div>
'INSTANT VB WARNING: An assignment within expression was extracted from the following statement:
'ORIGINAL LINE: <div class="result-section"> <button onclick="CopyToClipboard" class
		"result-section"> <button onclick="CopyToClipboard" class
		<div class="result-section"> <button onclick
	End If
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'</div>
VB   C#

标题和标题:标题和 `

标签分别定义页面标题和主标题,为用户设置上下文。

图片上传控制:一个该组件只接受图像文件,通过过滤掉不相关的文件类型来增强用户体验。

图片显示:上传图像后,图像将通过"......"显示。标签。这种视觉反馈对于确保用户上传了正确的文件至关重要。

扫描按钮:带有 @onclick="ScanQRCode 标记的按钮可触发扫描过程。它的可用性取决于文件是否被选中,从而增强了界面的直观性。

结果显示:扫描的二维码文本显示在文本输入框中,便于查看。另一个按钮允许用户将文本复制到剪贴板。

site.css 中的 CSS 样式

QR 码扫描器的视觉美感和布局在 "site.css "文件中定义。

.content {
    padding: 20px;
    margin: 10px auto; /* Centers the content */
    max-width: 500px; /* Sets a max width for the content */
    border-radius: 10px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.2);
    text-align: center;
}
.file-input, .result-input {
    margin: 10px 0;
    padding: 10px;
    border-radius: 5px;
    border: 1px solid #ddd;
    width: 100%;
}
.button {
    background-color: #4CAF50;
    color: white;
    border: none;
    cursor: pointer;
    padding: 10px;
    margin: 10px 0;
    border-radius: 5px;
    transition: background-color 0.3s, box-shadow 0.3s;
    width: auto; /* Adjusts button width */
    display: inline-block; /* Allows the width to adjust to content */
}
.button:hover {
    background-color: #45a049;
    box-shadow: 0 4px 8px rgba(0,0,0,0.2);
} 
.qr-image {
    max-width: 300px;
    max-height: 300px;
    display: block;
    margin: 10px auto;
    border-radius: 10px;
}
.result-section {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
}
.result-input {
    width: 100%;
    box-sizing: border-box;
}
.copy-button {
    margin-top: 10px;
    white-space: nowrap;
}

.content:该类对主要内容区域进行样式设计,使其具有确定的宽度、居中对齐方式和微妙的阴影效果。

.file-input, .result-input:这些类用于样式化文件输入和结果显示元素,确保它们在视觉上保持一致,并完全占据容器的宽度。

**按钮按钮采用独特的绿色背景、圆角和悬停效果,以实现更好的用户交互。

.qr-image:应用于二维码图像的样式包括尺寸限制和自动边距居中,使图像突出但不压抑。

.result-section:该类确保结果部分的元素居中对齐,间距适当。

处理文件上传

HandleSelectedFile "方法是二维码扫描过程的关键部分,用于处理用户上传的文件并为扫描做好准备。当用户通过 HandleSelectedFile 方法选择文件时,就会触发该方法。组件。如下代码所示:

private async Task HandleSelectedFile(InputFileChangeEventArgs e)
{
    selectedFile = e.File;
    fileSelected = true;
    var imagesDirectory = Path.Combine(Directory.GetCurrentDirectory(), "UploadedImages");
    Directory.CreateDirectory(imagesDirectory); // Ensure the directory exists
    // Use a GUID as the unique file name
    var uniqueFileName = Guid.NewGuid().ToString() + Path.GetExtension(selectedFile.Name);
    var fullPath = Path.Combine(imagesDirectory, uniqueFileName);
    await using (var fileStream = new FileStream(fullPath, FileMode.Create))
    {
        await selectedFile.OpenReadStream().CopyToAsync(fileStream);
    }
    // Store the full path in qrImageSrc for scanning
    qrImageSrc = fullPath;
    // Optionally, create a base64 string for displaying the image (if needed)
    byte [] imageBytes = await File.ReadAllBytesAsync(fullPath);
    var base64String = Convert.ToBase64String(imageBytes);
    qrImageSrcForDisplay = $"data:image/{Path.GetExtension(selectedFile.Name).TrimStart('.')};base64,{base64String}";
}
private async Task HandleSelectedFile(InputFileChangeEventArgs e)
{
    selectedFile = e.File;
    fileSelected = true;
    var imagesDirectory = Path.Combine(Directory.GetCurrentDirectory(), "UploadedImages");
    Directory.CreateDirectory(imagesDirectory); // Ensure the directory exists
    // Use a GUID as the unique file name
    var uniqueFileName = Guid.NewGuid().ToString() + Path.GetExtension(selectedFile.Name);
    var fullPath = Path.Combine(imagesDirectory, uniqueFileName);
    await using (var fileStream = new FileStream(fullPath, FileMode.Create))
    {
        await selectedFile.OpenReadStream().CopyToAsync(fileStream);
    }
    // Store the full path in qrImageSrc for scanning
    qrImageSrc = fullPath;
    // Optionally, create a base64 string for displaying the image (if needed)
    byte [] imageBytes = await File.ReadAllBytesAsync(fullPath);
    var base64String = Convert.ToBase64String(imageBytes);
    qrImageSrcForDisplay = $"data:image/{Path.GetExtension(selectedFile.Name).TrimStart('.')};base64,{base64String}";
}
Private Async Function HandleSelectedFile(ByVal e As InputFileChangeEventArgs) As Task
	selectedFile = e.File
	fileSelected = True
	Dim imagesDirectory = Path.Combine(Directory.GetCurrentDirectory(), "UploadedImages")
	Directory.CreateDirectory(imagesDirectory) ' Ensure the directory exists
	' Use a GUID as the unique file name
	Dim uniqueFileName = Guid.NewGuid().ToString() & Path.GetExtension(selectedFile.Name)
	Dim fullPath = Path.Combine(imagesDirectory, uniqueFileName)
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'	await using(var fileStream = New FileStream(fullPath, FileMode.Create))
'	{
'		await selectedFile.OpenReadStream().CopyToAsync(fileStream);
'	}
	' Store the full path in qrImageSrc for scanning
	qrImageSrc = fullPath
	' Optionally, create a base64 string for displaying the image (if needed)
	Dim imageBytes() As Byte = Await File.ReadAllBytesAsync(fullPath)
	Dim base64String = Convert.ToBase64String(imageBytes)
	qrImageSrcForDisplay = $"data:image/{Path.GetExtension(selectedFile.Name).TrimStart("."c)};base64,{base64String}"
End Function
VB   C#

下面是其功能的详细介绍:

文件选择和验证:当用户上传文件时,该方法会使用 InputFileChangeEventArgs e 捕获文件的详细信息,然后将 selectedFile 变量分配给该文件,并将布尔值 fileSelected 设为 true,表示输入数据/文件已准备好进行处理。

创建文件路径:该方法准备一个目录来存储上传的图片。它使用 Path.Combine 创建通往 "UploadedImages "目录的路径,并通过 Directory.CreateDirectory 确保该目录存在。这一步对于系统地组织上传的文件至关重要。

生成唯一文件名:为避免与现有文件冲突,将使用 GUID 生成唯一文件名 (全球唯一标识符) 附加了原始文件的扩展名。这可确保上传的每个文件都是 "唯一路径识别 "的。

保存文件:然后将文件保存到服务器。该方法会创建一个指向新生成文件路径的文件流,并使用 await selectedFile.OpenReadStream 将上传文件的内容复制到该文件流中。().CopyToAsync(文件流).此步骤完成上传过程。

准备显示图像:保存文件后,需要将图片显示给用户确认。该方法将文件读入一个字节数组,并将其转换为 base64 字符串,适合直接嵌入到......中。<img>标签的src` 属性。通过这种转换,无需向服务器单独请求图像文件,即可显示图像。

扫描 QR 码

ScanQRCode "方法是Blazor服务器应用程序中QR码扫描功能的核心。该方法接收上传的图片,并使用 IronQR 提取 QR 码数据。

private async Task ScanQRCode()
{   
    // Check if there is a valid image to work with
    if (string.IsNullOrEmpty(qrImageSrc)) return;
    try
    {
        var inputBmp = AnyBitmap.FromFile(qrImageSrc);
        QrImageInput imageInput = new QrImageInput(inputBmp);
        QrReader reader = new QrReader();
        IEnumerable<QrResult> results = reader.Read(imageInput);
        // Check if there are any results and if the first result contains text
        var firstResult = results.FirstOrDefault();
        if (firstResult != null && !string.IsNullOrWhiteSpace(firstResult.Value.ToString()))
        {
            scannedText = firstResult.Value.ToString();
        }
        else
        {
            scannedText = "QR value not found!";
        }
    }
    catch (Exception ex)
    {
        scannedText = "Error scanning QR code: " + ex.Message;
    }
}
private async Task ScanQRCode()
{   
    // Check if there is a valid image to work with
    if (string.IsNullOrEmpty(qrImageSrc)) return;
    try
    {
        var inputBmp = AnyBitmap.FromFile(qrImageSrc);
        QrImageInput imageInput = new QrImageInput(inputBmp);
        QrReader reader = new QrReader();
        IEnumerable<QrResult> results = reader.Read(imageInput);
        // Check if there are any results and if the first result contains text
        var firstResult = results.FirstOrDefault();
        if (firstResult != null && !string.IsNullOrWhiteSpace(firstResult.Value.ToString()))
        {
            scannedText = firstResult.Value.ToString();
        }
        else
        {
            scannedText = "QR value not found!";
        }
    }
    catch (Exception ex)
    {
        scannedText = "Error scanning QR code: " + ex.Message;
    }
}
Private Async Function ScanQRCode() As Task
	' Check if there is a valid image to work with
	If String.IsNullOrEmpty(qrImageSrc) Then
		Return
	End If
	Try
		Dim inputBmp = AnyBitmap.FromFile(qrImageSrc)
		Dim imageInput As New QrImageInput(inputBmp)
		Dim reader As New QrReader()
		Dim results As IEnumerable(Of QrResult) = reader.Read(imageInput)
		' Check if there are any results and if the first result contains text
		Dim firstResult = results.FirstOrDefault()
		If firstResult IsNot Nothing AndAlso Not String.IsNullOrWhiteSpace(firstResult.Value.ToString()) Then
			scannedText = firstResult.Value.ToString()
		Else
			scannedText = "QR value not found!"
		End If
	Catch ex As Exception
		scannedText = "Error scanning QR code: " & ex.Message
	End Try
End Function
VB   C#

首先,该方法会检查保存上传图片路径的 qrImageSrc 变量是否为空。此检查可确保在继续之前有一个有效的图片可供使用。

一旦确认图像可以处理,该方法就会进入 QR 码读取的核心功能。这涉及几个关键步骤,首先是将图像从其存储位置加载到适合 QR 码分析的格式。这种转换由 `AnyBitmap.FromFile(qrImageSrc)方法,为扫描过程准备图像。

下一步是创建 "QrReader "对象。该对象是 IronQR 库不可或缺的一部分,是从图像中解码二维码的主要工具。准备好 QrReader 实例后,应用程序就可以开始扫描上传的图片了。读取(图像输入)` 函数负责执行这一操作,有条不紊地搜索图像中的二维码并提取其数据。

扫描结果存储在一个 IEnumerable<QrResult>收集。然后仔细检查这个集合,找出第一个 QR 码结果。如果检测到 QR 码并包含可读文本,就会捕获该文本并将其存储到scannedText` 变量中。但是,如果未找到 QR 码或 QR 码不包含文本,应用程序会设置一条默认信息,告知用户未检测到 QR 值。

一旦二维码扫描成功,文本字符串就会显示在文本输入框中,这要归功于 Blazor 的双向数据绑定功能。这是通过将 scannedText 变量绑定到文本输入元素来实现的。输入框被设置为禁用,只读。这种设计将用户的交互重点放在查看结果和复制结果上,而不是编辑内容。

整个扫描过程都包含在一个 try-catch 块中,以防止在扫描操作过程中出现意外错误。这可能包括与图像文件格式有关的问题或读取过程中的意外错误。如果出现异常,就会被捕获,并生成错误信息显示给用户。这种方法不仅有助于发现问题,还能保持对用户的透明度,提高应用程序的可靠性。

复制结果

为启用复制到剪贴板功能,在 `_Host.cshtml``文件中定义了一个名为 "copyTextToClipboard "的 JavaScript 函数。该脚本是与剪贴板交互的一种简单而有效的方法:

<script>
    function copyTextToClipboard(text) {
        navigator.clipboard.writeText(text).then(function () {
            console.log('Copying to clipboard was successful!');
        }, function (err) {
            console.error('Could not copy text: ', err);
        });
    }
</script>
JAVASCRIPT

该函数接受一个文本参数,即要复制的文本。它使用 navigator.clipboard.writeText 方法,这是一种与剪贴板交互的现代方法。该方法因其简单性和符合网络标准而受到青睐。复制成功后,该方法会在控制台中记录一条成功信息,以帮助调试并确保功能顺畅。如果出现错误,则会在控制台中记录错误信息,以便深入了解操作过程中遇到的任何问题。

复制到剪贴板 "方法位于 index.razor 的"@code "部分,是 Blazor 应用程序与 JavaScript 函数之间的桥梁。用户界面中的按钮会触发该方法的点击。激活后,它会使用 Blazor 的 JavaScript InterOp 功能调用 copyTextToClipboard JavaScript 函数。扫描文本 "作为参数传递给该函数,从而有效地将文本复制到用户的剪贴板。

private async Task CopyToClipboard()
{
    await JSRuntime.InvokeVoidAsync("copyTextToClipboard", scannedText);
}
private async Task CopyToClipboard()
{
    await JSRuntime.InvokeVoidAsync("copyTextToClipboard", scannedText);
}
Private Async Function CopyToClipboard() As Task
	Await JSRuntime.InvokeVoidAsync("copyTextToClipboard", scannedText)
End Function
VB   C#

执行应用程序

运行项目后,用户将看到以下简洁的界面。初始界面突出显示了 QR 码扫描器模块。该模块包括一个上传二维码图像文件的按钮 (选择文件) 另一个用于启动扫描程序 (扫描 QR 码).起初没有选择文件,扫描区域为空白,等待用户输入。

如何创建 Blazor QR 码扫描器:图 6 - 项目初始执行结果

用户使用 "选择文件 "按钮选择并上传二维码图像,此时会显示所选文件的名称 (例如,"qrvalue.png).上传的 QR 代码会显示在界面的指定区域,向用户确认图像已准备好扫描。

如何创建 Blazor QR 码扫描器:图 7 - 用户输入二维码的结果

用户点击 "扫描 QR 码 "按钮后,应用程序就会处理图像。如果扫描成功,QR 码内的编码文本就会显示在图像下方。在这种情况下,扫描结果 ( '<https://ironsoftware.com/csharp/qr/>') 是一个 URL,表示用户使用 QR 阅读器扫描 QR 代码时的指向。结果旁边会出现 "复制 "按钮,用户可以轻松地将扫描文本复制到剪贴板上,以便进一步使用。

如何创建 Blazor QR 码扫描器:图 8 - 显示二维码文本和复制按钮

结论

如何创建 Blazor QR 码扫描器:图 9

总之,将 IronQR 集成到 Blazor 服务器应用程序中的过程既顺利又有效,最终形成了一个二维码扫描解决方案。由于 IronQR 强大的处理能力与 Blazor 动态用户界面渲染相结合,该项目从开始设置到实现扫描功能的整个过程都响应迅速、易于使用。从设置环境到部署的整个过程都体现了这种集成在实际应用中的实用性和有效性。虽然 IronQR 擅长 QR 码,但对于需要扫描条形码功能的项目来说,IronQR 是一个不错的选择、 IronBarcode 是一个理想的选择,可提供类似的便捷性和集成度。

IronQR 提供 免费试用 供开发人员在购买前探索其功能。如需在生产中扩展使用并访问其所有专业功能,IronQR 许可证的起价为 $749。

< 前一页
如何在 C# 中打印条形码
下一步 >
如何在VB .NET中打印条形码标签

准备开始了吗? 版本: 2024.8 刚刚发布

免费NuGet下载 总下载量: 1,167,541 查看许可证 >