#@veaba/qrcode-node
Node.js 环境的 QRCode 生成库,支持 SVG 和 PNG 输出,适合服务端渲染和文件生成。
#安装
npm install @veaba/qrcode-node#基础使用
#创建 QRCode
import { QRCode, QRErrorCorrectLevel } from '@veaba/qrcode-node';
// 创建 QRCode 实例
const qr = new QRCode('https://github.com/veaba/qrcodes', QRErrorCorrectLevel.H);
// 获取 SVG 字符串
const svg = qr.toSVG();
console.log(svg);#保存为文件
import { QRCode, QRErrorCorrectLevel } from '@veaba/qrcode-node';
import fs from 'fs';
const qr = new QRCode('https://github.com/veaba/qrcodes', QRErrorCorrectLevel.H);
// 保存 SVG
fs.writeFileSync('qrcode.svg', qr.toSVG());
// 保存 PNG
fs.writeFileSync('qrcode.png', qr.toPNG(256));#输出格式
#SVG 输出
const qr = new QRCode('https://github.com/veaba/qrcodes', QRErrorCorrectLevel.H);
// 基础 SVG(默认 256x256)
const svg = qr.toSVG();
// 指定尺寸
const largeSvg = qr.toSVG(512);#PNG 输出
const qr = new QRCode('https://github.com/veaba/qrcodes', QRErrorCorrectLevel.H);
// 生成 PNG Buffer(默认 256x256)
const pngBuffer = qr.toPNG();
// 指定尺寸
const largePng = qr.toPNG(512);
// 保存文件
fs.writeFileSync('qrcode.png', pngBuffer);#终端输出
在终端中直接显示二维码,支持多种渲染方式:
const qr = new QRCode('https://example.com', QRErrorCorrectLevel.M);
// 标准终端输出(使用 █ 字符)
console.log(qr.toTerminal());
// 反转颜色
console.log(qr.toTerminal(true));
// 大静区
console.log(qr.toTerminal(false, 3));
// Braille 紧凑输出(高度约为标准的 1/4)
console.log(qr.toTerminalBraille());
// 彩色输出(支持 8 种颜色)
console.log(qr.toTerminalColor('green'));
console.log(qr.toTerminalColor('blue', 'yellow')); // 前景 + 背景#终端输出示例
标准输出:
██████████████ ██████████████ ██████████████
██ ██ ██ ██████ ██████ ██ ██
██ ██████ ██ ████ ████ ██ ██████ ██
██ ██████ ██ ████ ████ ██ ██████ ██
██████████████ ██ ██ ██ ██ ██ ██████████████Braille 输出:
⠟⣝⠝⠏⡌⡒⢱⢮⠃⠟⣝⠝⠏
⡇⡕⡅⠇⠟⠥⠔⠮⠍⡇⡕⡅⠇
⣭⣕⢿⠅⡎⢪⣡⣄⠬⣹⡑⡡⠌#支持的颜色
black, red, green, yellow, blue, magenta, cyan, white
#使用场景
- 在 CI/CD 日志中显示二维码
- TUI 应用中直接渲染
- 快速预览二维码内容
- 无需图形界面即可分享二维码
#样式化 SVG
const qr = new QRCode('https://github.com/veaba/qrcodes', QRErrorCorrectLevel.H);
const styledSvg = qr.toStyledSVG({
size: 256,
colorDark: '#000000',
colorLight: '#ffffff',
borderRadius: 8,
quietZone: 2,
gradient: {
color1: '#667eea',
color2: '#764ba2'
}
});
fs.writeFileSync('styled-qrcode.svg', styledSvg);#Web 服务集成
#Express 示例
import express from 'express';
import { QRCode, QRErrorCorrectLevel } from '@veaba/qrcode-node';
const app = express();
// SVG 端点
app.get('/qrcode.svg', (req, res) => {
const { text = 'https://github.com/veaba/qrcodes', size = 256 } = req.query;
const qr = new QRCode(text, QRErrorCorrectLevel.H);
const svg = qr.toStyledSVG({
size: parseInt(size),
borderRadius: 8
});
res.setHeader('Content-Type', 'image/svg+xml');
res.send(svg);
});
// PNG 端点
app.get('/qrcode.png', (req, res) => {
const { text = 'https://github.com/veaba/qrcodes', size = 256 } = req.query;
const qr = new QRCode(text, QRErrorCorrectLevel.H);
const png = qr.toPNG(parseInt(size));
res.setHeader('Content-Type', 'image/png');
res.send(png);
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
console.log('Try: http://localhost:3000/qrcode.svg?text=Hello&size=256');
});#Fastify 示例
import Fastify from 'fastify';
import { QRCode, QRErrorCorrectLevel } from '@veaba/qrcode-node';
const fastify = Fastify();
fastify.get('/qrcode', async (request, reply) => {
const { text = 'https://github.com/veaba/qrcodes', size = 256, type = 'svg' } = request.query;
const qr = new QRCode(text, QRErrorCorrectLevel.H);
if (type === 'png') {
reply.header('Content-Type', 'image/png');
return qr.toPNG(parseInt(size));
} else {
reply.header('Content-Type', 'image/svg+xml');
return qr.toSVG(parseInt(size));
}
});
fastify.listen({ port: 3000 });#Next.js API Route
// pages/api/qrcode.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { QRCode, QRErrorCorrectLevel } from '@veaba/qrcode-node';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { text = 'https://github.com/veaba/qrcodes', size = 256 } = req.query;
const qr = new QRCode(text as string, QRErrorCorrectLevel.H);
const svg = qr.toSVG(parseInt(size as string));
res.setHeader('Content-Type', 'image/svg+xml');
res.status(200).send(svg);
}#批量生成
import { QRCode, QRErrorCorrectLevel } from '@veaba/qrcode-node';
import fs from 'fs';
import path from 'path';
const urls = [
'https://github.com/veaba/qrcodes/product/1',
'https://github.com/veaba/qrcodes/product/2',
'https://github.com/veaba/qrcodes/product/3'
];
// 批量生成
const outputDir = './qrcodes';
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}
urls.forEach((url, index) => {
const qr = new QRCode(url, QRErrorCorrectLevel.H);
// 生成 SVG
fs.writeFileSync(
path.join(outputDir, `qrcode-${index + 1}.svg`),
qr.toSVG(256)
);
// 生成 PNG
fs.writeFileSync(
path.join(outputDir, `qrcode-${index + 1}.png`),
qr.toPNG(256)
);
});
console.log(`Generated ${urls.length} QR codes`);#错误处理
import { QRCode, QRErrorCorrectLevel } from '@veaba/qrcode-node';
try {
// 文本过长会抛出错误
const longText = 'a'.repeat(1000);
const qr = new QRCode(longText, QRErrorCorrectLevel.H);
const svg = qr.toSVG();
} catch (error) {
console.error('Failed to generate QR code:', error.message);
// 处理错误,例如返回默认图片或错误信息
}#CLI 工具
可以创建一个简单的 CLI 工具:
#!/usr/bin/env node
// qrcode-cli.ts
import { QRCode, QRErrorCorrectLevel } from '@veaba/qrcode-node';
import fs from 'fs';
const [,, text, output = 'qrcode.png'] = process.argv;
if (!text) {
console.log('Usage: qrcode-cli <text> [output]');
process.exit(1);
}
const qr = new QRCode(text, QRErrorCorrectLevel.H);
if (output.endsWith('.svg')) {
fs.writeFileSync(output, qr.toSVG(256));
} else {
fs.writeFileSync(output, qr.toPNG(256));
}
console.log(`Generated: ${output}`);#API 参考
#QRCode 类
| 方法 | 说明 | 参数 | 返回值 |
|---|---|---|---|
constructor(text, level) | 构造函数 | text: string, level: QRErrorCorrectLevel | QRCode |
toSVG(size?) | 生成 SVG | size?: number | string |
toPNG(size?) | 生成 PNG | size?: number | Buffer |
toStyledSVG(options) | 样式化 SVG | options: StyledSVGOptions | string |
toTerminal(invert?, quietZone?) | 终端输出 | invert?: boolean, quietZone?: number | string |
toTerminalBraille() | Braille 终端输出 | - | string |
toTerminalColor(fg?, bg?) | 彩色终端输出 | fg?: string, bg?: string | string |
getModuleCount() | 获取模块数 | - | number |
isDark(row, col) | 判断模块颜色 | row: number, col: number | boolean |
#QRErrorCorrectLevel
enum QRErrorCorrectLevel {
L = 1, // ~7% 容错
M = 0, // ~15% 容错
Q = 3, // ~25% 容错
H = 2 // ~30% 容错
}#与前端包的区别
| 特性 | @veaba/qrcode-node | @veaba/qrcode-js |
|---|---|---|
| 环境 | Node.js | 浏览器 |
| PNG 支持 | ✅ 原生 Buffer | ❌ 需额外处理 |
| 文件系统 | ✅ 直接写入 | ❌ 需下载 |
| 服务端渲染 | ✅ 支持 | N/A |
| 性能 | 快 | 快 |
#性能数据
基于实际基准测试:
| 测试项 | 性能 |
|---|---|
| 单条生成 (medium) | 9,662 ops/s |
| 批量生成 (100 条) | 3,000 ops/s |
| SVG 输出 | 9,827 ops/s |
| PNG Buffer 输出 | 2,404 ops/s |
测试环境:Node.js v20.19.4, Windows