用 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或生成空白图。
常见错误现象:
输出图片全是白的 → 忘了 newQRCode实例,或传了空/无效的
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。
