qrcoder库最省事,不依赖system.drawing,避免.net 6+跨平台问题;需先用qrcodegenerator编码再用qrcode渲染,注意纠错等级、quietzonepercent及bitmap释放。

用 QRCoder 库最省事,别自己造轮子
直接上 NuGet 装 QRCoder,它不依赖 System.Drawing(避免 .NET 6+ 中的跨平台问题),生成快、API 直观。自己调用 System.Drawing.Common 手动画点容易在 Linux/macOS 上报 PlatformNotSupportedException,而且编码逻辑(比如纠错等级、掩码模式)藏得深,改错成本高。
实操建议:
- 在项目中运行
dotnet add package QRCoder或通过 VS NuGet 管理器安装QRCoder(注意选官方作者CodePlexArchive的那个,不是同名但无维护的分支) - 避免用已弃用的
QRCoder.NETCore——它只兼容旧版 .NET Core,且不更新 - 如果项目是 .NET Framework 4.6.1+,也推荐统一用主库
QRCoder,行为一致,迁移成本低
QRCodeGenerator 和 QRCode 两步不能少
生成二维码不是调一个函数就完事:先用 QRCodeGenerator 编码内容为数据结构,再用 QRCode 渲染成图片。跳过前者直接传字符串给绘图方法,会报 ArgumentNullException 或生成空白图。
常见错误现象:
- 输出图片全是白的 → 忘了 new
QRCode实例,或传了空/无效的QRCodeData - 中文乱码或 URL 截断 → 没设
QRCodeGenerator.ECCLevel,默认用M纠错,但长文本+中文需要Q或H才够容量 - 生成的 PNG 在某些微信里扫不出 → 没设置
QRCode.GetGraphic的quietZonePercent参数(建议至少15,否则边缘太紧)
简短示例:
var generator = new QRCodeGenerator();
var data = generator.CreateQrCode("https://example.com/测试", QRCodeGenerator.ECCLevel.Q);
var qrCode = new QRCode(data);
var bitmap = qrCode.GetGraphic(20, Color.Black, Color.White, null, null, 15); // 最后一个 15 是 quiet zone
bitmap.Save("qrcode.png", ImageFormat.Png);
保存为文件时注意 Bitmap 生命周期和路径权限
QRCode.GetGraphic 返回的是 Bitmap,它底层持有着 GDI+ 句柄。如果没及时释放,反复生成会触发 OutOfMemoryException,尤其在 Web API 或长时间运行服务里。
使用场景差异:
- 控制台或单次工具:用
using包住Bitmap即可 - ASP.NET Core API:别直接
Save()到磁盘路径,优先返回FileStreamResult;若真要落盘,确保目录存在且应用有写权限(Linux 下常因/var/www权限不足静默失败) - 路径含中文或空格:
Save()本身支持,但若路径来自用户输入,需先用Path.GetInvalidFileNameChars()过滤非法字符,否则抛ArgumentException
.NET 6+ 中 System.Drawing 不可用?QRCoder 已内置绕过方案
很多人卡在这儿:升级到 .NET 6 后,编译不报错,但一运行就崩在 new Bitmap(),提示 System.Drawing.Common is not supported on this platform。这不是 QRCoder 的锅——它默认用纯托管的 PngByteQRCode 或 BitmapByteQRCode,根本没碰 System.Drawing。
关键点:
- 只要你不显式调用
QRCode.GetGraphic(它内部才用Bitmap),而是用QRCode.GetMatrix()+ 自己写 PNG 编码,就完全规避该问题 - 或者直接用
QRCode.GetRawImage(v1.4.4+)返回byte[],再用File.WriteAllBytes保存,全程不触碰图形 API - 检查是否误引用了旧版示例代码——有些博客贴的还是基于
System.Drawing的封装,那些在新版本里必须重写
真正麻烦的不是生成,是有人把 QRCodeData 存数据库、等下次再渲染,结果发现不同版本 QRCoder 对同一串文本生成的矩阵不一致(比如 v1.4.3 和 v1.4.4 的掩码策略微调)。这种场景下,版本号得锁死,不能只写 ^1.4。










