c# 如何生成二维码

15次阅读

ZXing.net 是 C# 中最稳定、兼容性好、文档全的二维码生成方案,支持 .NET Framework 4.5+ 及 .NET Core 3.1+ 以上全平台,推荐通过 NuGet 安装并配置 BarcodeWriter 与 QrCodeEncodingoptions(含 UTF-8、高容错、合理尺寸与边距),注意空输入校验、资源释放、ui 线程安全及文件保存健壮性。

c# 如何生成二维码

ZXing.NET 是目前 C# 中最稳定、兼容性最好、文档最全的二维码生成方案,推荐直接用它,别折腾老库(如 ThoughtWorks.QRCode)或已停更的封装。它支持 .NET Framework 4.5+、.NET Core 3.1+ 和 .NET 5/6/7/8,winForms、wpf、ASP.NET Core 全能跑。


安装 ZXing.NET 并初始化写入器

不手动下载 DLL,也不拖引用——用 NuGet 命令一行搞定:

dotnet add package ZXing.Net

或在 visual studio 包管理器控制台运行:

Install-Package ZXing.Net

然后在代码中引入命名空间

using ZXing; using ZXing.Common; using ZXing.QrCode;

关键点:

  • BarcodeWriter 是生成入口,必须指定 format = BarcodeFormat.QR_CODE
  • 必须显式配置 QrCodeEncodingOptions,否则中文乱码、尺寸失控、容错低
  • 别漏掉 options.CharacterSet = "UTF-8",否则 TextBox 输入中文会变问号或报错

生成带中文内容的二维码(含防空校验)

常见错误:用户没输内容就点“生成”,writer.Write("") 直接抛 ArgumentNullException

正确做法是加一层判断,并设置默认占位符:

private Bitmap GenerateQrCode(string content) {     if (string.IsNullOrWhiteSpace(content))         content = "QR_EMPTY"; 
var writer = new BarcodeWriter {     Format = BarcodeFormat.QR_CODE,     Options = new QrCodeEncodingOptions     {         DisableECI = true,         CharacterSet = "UTF-8",         Width = 300,         Height = 300,         margin = 2,         ErrorCorrection = ErrorCorrectionLevel.H // 高容错,推荐 M 或 H     } }; return writer.Write(content);

}

说明:

  • ErrorCorrectionLevel.H 比默认的 M 更抗划伤/污损,适合打印场景
  • Margin = 2 表示白边宽度(单位:模块数),太小(如 0)会导致扫码器无法识别
  • 尺寸 Width/Height 建议设为 200~400,再小易糊,再大无意义(手机摄像头解析力有限)

保存为 PNG 文件并防止文件冲突

直接 bitmap.Save("xxx.png") 很危险:并发请求、重复点击、路径不存在都会崩。

安全写法要包含三件事:目录创建 + 唯一文件名 + 异常后释放资源:

public string SaveQrCode(Bitmap bitmap, string folderPath, string fileName = null) {     var dir = Path.Combine(appDomain.CurrentDomain.BaseDirectory, folderPath);     Directory.CreateDirectory(dir); 
fileName ??= $"qrcode_{DateTime.Now:yyyyMMddHHmmssfff}.png"; var fullPath = Path.Combine(dir, fileName);  try {     bitmap.Save(fullPath, ImageFormat.Png);     return fullPath; } catch (Exception ex) {     throw new InvalidOperationException($"保存二维码失败: {ex.Message}", ex); } finally {     bitmap?.Dispose(); // 必须释放,否则内存泄漏 }

}

注意:

  • 不要用 AppDomain.CurrentDomain.BaseDirectory 在 ASP.NET Core 中——改用 IWebHostEnvironment.WebRootPath
  • 文件名里加毫秒级时间戳(fff)可基本避免重名,无需 GUID
  • WinForms 中若直接赋给 PictureBox.Image,记得先 Dispose() 旧图,否则 GDI 句柄耗尽

WinForms 点击按钮生成并显示到 PictureBox

这是最典型场景,但新手常卡在两处:图片不显示、界面卡死(因没走 UI 线程)。

完整事件处理逻辑如下:

private void btnGenerate_Click(object sender, EventArgs e) {     var text = textBoxInput.Text.Trim();     if (string.IsNullOrEmpty(text))     {         MessageBox.Show("请输入内容", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);         return;     } 
try {     var qrBitmap = GenerateQrCode(text);     // WinForms 必须在 UI 线程设置 Image     pictureBox1.Invoke((MethodInvoker)delegate     {         pictureBox1.Image?.Dispose();         pictureBox1.Image = qrBitmap;     }); } catch (Exception ex) {     MessageBox.Show($"生成失败:{ex.Message}"); }

}

关键提醒:

  • 永远不要在非 UI 线程直接操作控件(比如后台线程调 pictureBox1.Image = ...
  • pictureBox1.Image 赋值前不 Dispose() 旧图,多次点击后内存暴涨、程序变慢
  • 如果后续要打印,别用 PictureBox.Image 原图——它可能被缩放失真,应另存高清源图再送打印

生成二维码本身不难,难的是让每一处边界条件都稳住:空输入、中文、高并发、UI 线程、资源释放、跨平台路径。这些细节起来,才是生产可用的代码。

text=ZqhQzanResources