跳到主要内容
版本:3.1

条码生成工具(Aegis.Toolkit.Barcode)

Aegis.Toolkit.Barcode 用来生成二维码和一维条形码,输出黑白 PNG。编码基于 ZXing.Net,PNG 编码只依赖 .NET 基类库。纯静态类调用,不需要 DI 注册,也不需要 Component.deps.json 声明。

组件概览​

字段说明
组件名称条码生成工具
真实类库Aegis.Toolkit.Barcode
组件定位二维码/一维条形码生成工具包
引入方式安装 NuGet,引用命名空间后直接调用静态类
是否需要 Component.deps.json否
核心能力QrCodeGenerator、BarcodeGenerator,各含 ToPng / ToBase64 / ToDataUri / WriteTo
典型配套无,任意 Aegis 服务或独立项目均可引用

什么时候要用它​

适合场景:

  • 页面或报表里要展示二维码/条形码(挂号单、检验报告、收银小票、资产标签)
  • 接口要把条码图片回给前端(PNG 字节或 data URI)
  • 要把条码写进文件或嵌入 PDF 附件

不适合场景:

  • 识别、解码条码(本包只生成,不读取)
  • 彩色条码、Logo 合成、矢量格式(SVG)输出(拿 PNG 字节自行后处理)

最小可运行路径​

第一步:安装包​

dotnet add package Aegis.Toolkit.Barcode --version 3.1.0

第二步:直接调用​

using Aegis.Toolkit.Barcode;

// 二维码:默认纠错 Medium、每模块 4px、四周留白 4 模块
byte[] qrPng = QrCodeGenerator.ToPng("https://example.com/report/1001");

// 一维条形码:默认窄条 2px、条高 60px、左右留白 20px
byte[] barPng = BarcodeGenerator.ToPng("Aegis-123", BarcodeSymbology.Code128);

没有第三步。不注册 DI,不写配置文件。

Service 封装:Base64 与文件流两套标准用法​

业务项目里按框架惯例封到 Service 层:契约继承 IBusinessService 放 Contract 工程,实现放 Services 工程,BusinessServices 自动注册。渲染选项集中在实现里维护。

方案一:Base64​

using Aegis.Services;
using Aegis.Toolkit.Barcode;

public interface IBarcodeService : IBusinessService
{
/// <summary>二维码 PNG 的 Base64</summary>
string GetQrBase64(string content);
}

public class BarcodeService : IBarcodeService
{
private readonly QrCodeOptions _qrOptions = new() { ModulePixels = 6 };

public string GetQrBase64(string content)
=> QrCodeGenerator.ToBase64(content, _qrOptions);
}

控制器 SuccessResult(_barcodeService.GetQrBase64(content)) 回给前端,拼上 data:image/png;base64, 前缀即可放进 img;想免拼接,把 ToBase64 换成 ToDataUri。

方案二:文件流​

public interface IBarcodeService : IBusinessService
{
/// <summary>把二维码 PNG 写入流(不关闭、不刷新传入的流)</summary>
void WriteQrTo(string content, Stream stream);
}

流的去向由调用方决定,两种常见走法:

// 自行落盘
await using var fileStream = new FileStream("qr-1001.png", FileMode.Create, FileAccess.Write);
_barcodeService.WriteQrTo("https://example.com/report/1001", fileStream);

// 走框架文件系统存储:FileManager 接收流后上传(NAS / S3 同一接口)
await using var stream = new MemoryStream();
_barcodeService.WriteQrTo(content, stream);
stream.Position = 0;
var result = await _fileManager.UploadFileAsync("qr-1001.png", stream);

接口直接回图片也是流的一种去向,写法见「高级用法 → 接口直接返回条码图片」。

两个入口怎么选​

入口生成什么主方法签名
QrCodeGenerator二维码ToPng(content, options?)
BarcodeGenerator一维条形码ToPng(content, symbology, options?)

两个入口的输出方法完全对称:

方法返回用途
ToPngbyte[]PNG 字节,写文件、上传、嵌入 PDF
ToBase64stringPNG 内容的裸 Base64,不含前缀
ToDataUristringdata:image/png;base64,...,直接放 img 的 src
WriteTovoid写入流(文件流、HTTP 响应流),不关闭、不刷新传入的流

配置项说明​

QrCodeOptions(二维码)​

字段类型默认值说明
ErrorCorrectionErrorCorrectionLevelMedium纠错级别:Low 约 7%、Medium 约 15%、Quartile 约 25%、High 约 30%
ModulePixelsint4每模块像素数,不小于 2 扫码器才好识别
MarginModulesint4四周留白模块数,4 是 QR 规范最小值,不建议再小

BarcodeOptions(一维条形码)​

字段类型默认值说明
ModuleWidthint2窄条宽度(像素)
HeightPixelsint60条高(像素)
MarginPixelsint20左右留白(像素),GS1 建议 10 倍窄条宽

两个 Options 的字段全部带默认值、init-only,可以直接从 JSON 反序列化后传入。

BarcodeSymbology(一维码制)​

码制内容要求典型用途
Code128全 ASCII物流、仓储首选
Code39大写字母 + 数字 + 少量符号(见常见问题)工业传统码制
Ean1312 位自动补校验位,或 13 位含正确校验位商品零售
Ean87 位自动补校验位,或 8 位含正确校验位商品零售短码
UpcA11 位自动补校验位,或 12 位含正确校验位北美商品零售
Itf纯数字,位数必须是偶数仓储、包装箱
Codabar数字 + $ - : . / +图书馆、血库

内容不满足码制要求(长度非法、字符不支持、校验位错误)时抛 BarcodeException,消息里带码制名和内容线索,好定位问题。

高级用法​

接口直接返回条码图片​

app.MapGet("/barcode/{code}", (string code) =>
Results.File(BarcodeGenerator.ToPng(code, BarcodeSymbology.Code128), "image/png"));

写文件(两种写法等价)​

using var stream = File.Create("label.png");
BarcodeGenerator.WriteTo("Aegis-123", stream, BarcodeSymbology.Code128);

// 或者
File.WriteAllBytes("label.png", BarcodeGenerator.ToPng("Aegis-123", BarcodeSymbology.Code128));

data URI 进页面​

var src = QrCodeGenerator.ToDataUri("https://example.com/report/1001");
<img src="@src" alt="报告二维码" />

Razor 页面里直接拼进 src,或者把字符串放进 JSON 回给前端。

中文与 emoji​

二维码固定 UTF-8 字符集,中文、emoji 不需要额外设置:

var png = QrCodeGenerator.ToPng("德真健康-检验报告单-2026");

印制环境差时用 High 纠错​

var png = QrCodeGenerator.ToPng(
"https://example.com/report/1001",
new QrCodeOptions { ErrorCorrection = ErrorCorrectionLevel.High });

热敏纸打印、标签易磨损、要在二维码中心叠图标的场景用 High,可纠错约 30%。纠错级别越高内容容量越小,屏幕展示用默认 Medium 就够。

自定义扩展​

本包是静态工具类,没有继承基类或实现接口的扩展点,渲染参数由 QrCodeOptions / BarcodeOptions 覆盖。要加能力有两条路:

  • 拿 ToPng 返回的 byte[] 自行后处理(合成、嵌入 PDF)
  • 直接引用 ZXing.Net 在业务项目内编码更底层的格式

包内 Internal/ 下的类型不对外保证兼容,业务代码不要依赖。

接入后怎么确认生效​

  • 生成的字节以 PNG 文件签名开头,存成 .png 文件后能被图片查看器打开
  • 用手机或扫码枪扫生成的图片,读出的内容与输入一致
  • 仓库单测 35 个全绿,其中有端到端用例:自产 QR 中文 PNG 用 ZXing Reader 回读文本一致,自产 Code128 PNG 回读内容一致。怀疑输出有问题时,用同样的"生成再回读"思路自验一遍

常见问题​

为什么条码扫不出来​

按顺序排查:ModuleWidth 是不是小于 2;一维码左右留白 MarginPixels 是不是被改小了(GS1 建议 10 倍窄条宽);Code39 内容是不是带了小写或符号(见下一问)。

Code39 内容带小写为什么没报错,扫码器却读不出来​

Code39 在 ZXing 中走扩展编码(全 ASCII 转义序列),小写与符号会被编码成转义序列,生成端不报错。普通扫码器默认按标准 Code39 模式解读,读不出这些转义内容。内容只用大写字母 + 数字。

EAN-13 传 12 位还是 13 位​

都行。传 12 位自动补第 13 位校验位;传 13 位时校验位必须正确,否则抛 BarcodeException。EAN-8(7/8 位)、UPC-A(11/12 位)同理。

WriteTo 之后流怎么没关​

WriteTo 只写不关,打开和关闭由调用方负责。这样同一个流可以继续写别的内容,也避免误关 HTTP 响应流。

ModulePixels 能不能设很大​

建议控制在 2-16。极端大值时像素缓冲区的 width * height 会触碰 int 溢出边界(回绕成负数),就算没溢出,一张几亿像素的图也会先 OOM。要大图就小幅上调并实测内存。

为什么只有黑白 PNG​

输出固定 8bit 灰度 PNG(0 黑、255 白)。条码场景只需要黑白两色,PNG 编码因此不依赖任何图像库。要彩色或矢量格式,拿 byte[] 自行后处理。

配套阅读​