HTTP API
约 3722 字大约 12 分钟
...
2026-09-29
说明
打印客户端(sv-print-client)内置 HTTP 服务,基于 ee-core(Koa)实现,用于在浏览器、后端服务等场景下通过 REST 方式调用客户端能力。
服务地址与端口(以代码为准):
| 配置项 | 默认值 | 说明 |
|---|---|---|
httpPort | 7071 | HTTP 服务端口,最小 1024 |
enableHttp | true | 是否开启 HTTP 服务 |
enableHttps | - | 是否启用 HTTPS(启用后使用内置自签证书,以 https:// 访问) |
| host | 0.0.0.0 | 监听所有网卡,局域网内其他设备可直接访问 |
端口与开关在客户端设置界面修改,持久化于用户配置文件 config.json。以下均以默认地址 http://localhost:7071 为例。
路由规则
- 路径格式:
/{controller}/{method},/controller前缀可省略(服务端自动补全),即http://localhost:7071/controller/printer/list与http://localhost:7071/printer/list等价。 controller为控制器文件名:app、printer、log、framework;method为控制器类的公开方法名。- 参数传递:
POST使用 JSON body(Content-Type: application/json),GET使用 query。请求参数整体作为第一个实参传入控制器方法,方法内从参数对象中解构对应字段。 - 返回:控制器方法的返回值直接 JSON 序列化返回,无统一包装结构,HTTP 状态码为 200。方法不存在或执行异常时返回空响应,错误记录在客户端日志中。
- 路径过滤:
.json结尾、favicon.ico、/static、/public开头的请求不进入控制器分发(静态资源等)。 - JSON body 默认上限约 1MB(koa-body
jsonLimit默认值),大模板打印建议改用 Socket.IO(默认端口17521)。
关于鉴权
HTTP 接口本身无鉴权,且 CORS 允许所有来源。配置中的 authKey 是 sv-print 渲染授权 key(影响模板渲染打印水印),不是 HTTP 鉴权凭证。请勿将客户端端口直接暴露到公网。
接口列表
printer 打印机相关
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /controller/printer/list | 打印机列表 |
| POST | /controller/printer/setDefaultPrinter | 设置默认打印机 |
| POST | /controller/printer/disablePrinter | 禁用打印机 |
| POST | /controller/printer/enablePrinter | 启用打印机 |
| POST | /controller/printer/showPrintView | 显示打印机打印窗口 |
| POST | /controller/printer/openDevTools | 打开打印窗口开发者工具 |
| POST | /controller/printer/print | 执行打印 |
| GET | /controller/printer/clientsCount | 已连接 Socket/MQTT 客户端数量 |
| GET | /controller/printer/clients | 已连接 Socket/MQTT 客户端信息 |
app 应用与配置相关
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /controller/app/baseInfo | 应用基础信息 |
| GET | /controller/app/config | 获取完整配置 |
| POST | /controller/app/updateConfig | 更新配置 |
| GET | /controller/app/relaunch | 重启客户端 |
| GET | /controller/app/openConfig | 用系统编辑器打开配置文件 |
| GET | /controller/app/importConfig | 弹窗导入配置文件 |
| GET | /controller/app/exportConfig | 弹窗导出配置文件 |
| POST | /controller/app/loadConfigOrRenderer | 导入配置/自定义渲染文件 |
| GET | /controller/app/getTemplate | 本地模板列表 |
| POST | /controller/app/saveTemplate | 保存本地模板 |
| POST | /controller/app/deleteTemplate | 删除本地模板(见小节说明) |
| POST | /controller/app/print | 执行打印(同 printer/print) |
| GET | /controller/app/checkCustomUpdate | 检查自定义渲染更新 |
| POST | /controller/app/downloadCustom | 下载自定义渲染包 |
| POST | /controller/app/installCustom | 安装自定义渲染包 |
| POST | /controller/app/openDesignerUrl | 打开在线设计器窗口 |
| GET | /controller/app/checkUpdate | 检查应用新版本 |
| GET | /controller/app/downloadApp | 下载新版本 |
| GET | /controller/app/installApp | 安装新版本 |
| GET | /controller/app/windowMinimize | 最小化/隐藏主窗口 |
| GET | /controller/app/toggleMaximize | 最大化/还原切换 |
| POST | /controller/app/windowMaximize | 最大化/还原(见小节说明) |
| GET | /controller/app/windowClose | 关闭窗口(不退出应用) |
log 打印日志相关
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /controller/log/printLogList | 打印日志列表(分页查询) |
| POST | /controller/log/rePrint | 重新打印 |
| POST | /controller/log/preview | 预览某条打印日志的打印数据 |
printer 接口
printer/list 打印机列表
- 方法+路径:
GET /controller/printer/list - 参数:无
- 返回:打印机对象数组。元素在 Electron
PrinterInfo基础上扩展了三个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
name / displayName / description / status / options | - | Electron PrinterInfo 原生字段 |
disabled | boolean | 是否被客户端禁用 |
isDefault | boolean | 是否为客户端设置的默认打印机 |
isOk | boolean | 打印机状态是否正常(win32 正常值为 0,macOS/Linux 为 3) |
curl http://localhost:7071/controller/printer/listconst printers = await axios.get('http://localhost:7071/controller/printer/list');
// 过滤可用打印机
const available = printers.data.filter((p) => !p.disabled && p.isOk);printer/setDefaultPrinter 设置默认打印机
- 方法+路径:
POST /controller/printer/setDefaultPrinter - 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
printerName | string | 是 | 打印机名称 |
- 返回:boolean。成功
true;打印机处于禁用列表时返回false。
curl -X POST http://localhost:7071/controller/printer/setDefaultPrinter \
-H "Content-Type: application/json" \
-d '{"printerName":"Microsoft Print to PDF"}'printer/disablePrinter 禁用打印机
- 方法+路径:
POST /controller/printer/disablePrinter - 参数:
printerName(string,必填) - 返回:boolean。已处于禁用状态时返回
false;禁用成功返回true,同时销毁对应打印窗口并向客户端主窗口发送事件。
curl -X POST http://localhost:7071/controller/printer/disablePrinter \
-H "Content-Type: application/json" \
-d '{"printerName":"XP-58"}'printer/enablePrinter 启用打印机
- 方法+路径:
POST /controller/printer/enablePrinter - 参数:
printerName(string,必填) - 返回:boolean。未在禁用列表中时返回
false;启用成功返回true,并重建对应打印(渲染)窗口。
curl -X POST http://localhost:7071/controller/printer/enablePrinter \
-H "Content-Type: application/json" \
-d '{"printerName":"XP-58"}'printer/showPrintView 显示打印窗口
- 方法+路径:
POST /controller/printer/showPrintView - 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
printerName | string | 是 | 打印机名称 |
isRenderer | boolean | 否 | 是否为模板渲染窗口,默认 false |
- 返回:boolean。窗口存在(或自动创建成功)返回
true。
curl -X POST http://localhost:7071/controller/printer/showPrintView \
-H "Content-Type: application/json" \
-d '{"printerName":"XP-58","isRenderer":true}'printer/openDevTools 打开打印窗口开发者工具
- 方法+路径:
POST /controller/printer/openDevTools - 参数:同
showPrintView(printerName、isRenderer) - 返回:boolean。调试模板渲染窗口时使用;已打开则先关闭再重新打开。
curl -X POST http://localhost:7071/controller/printer/openDevTools \
-H "Content-Type: application/json" \
-d '{"printerName":"XP-58","isRenderer":true}'printer/print 执行打印
- 方法+路径:
POST /controller/printer/print - 参数:
EventData打印事件对象,主要字段:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
printer | string | 否 | 打印机名称,不传使用客户端默认打印机 |
printType | string | 否 | 打印类型,一般无需传入,由数据自动推断 |
type | string | 否 | 指定特殊打印类型:pdf / url_pdf / capture |
html | string | - | HTML 打印内容,传入后按 html 类型打印 |
template | string | object | - | 模板 JSON(对象或字符串),传入后按 template 类型打印 |
tempId | string | number | - | 本地模板 id,传入后自动加载 templateList / templateUrl 中的模板 |
templateId | string | 否 | 本次打印标识,用于回调匹配 |
pdf_path | string | - | url_pdf 类型必填:网络地址(http/https,自动下载)或本地绝对路径 |
toNet | boolean | 否 | pdf/capture 结果是否复制到静态目录并通过 data.url 返回可访问地址 |
buffer | boolean | 否 | pdf/capture 结果是否在返回值中携带 buffer 数据 |
captureType | string | 否 | capture 输出类型:jpeg / png,默认 jpeg |
captureOptions | object | 否 | 传给 snapdom.toCanvas 的参数 |
print_options | object | string | 否 | 打印选项(对象或 JSON 字符串),会展开到参数顶层 |
| 其余 | - | - | 继承 Electron WebContentsPrintOptions、PrintToPDFOptions、pdf-to-printer PrintOptions,如 silent、printBackground、margins、copies、landscape、pageSize 等 |
打印类型推断规则:传 html 按 html 打印;传 template/tempId 按 template 打印;type 指定 pdf/url_pdf/capture 时优先;都不满足时为 other(返回失败:未知打印类型)。
- 返回:
TaskResult(打印任务完成后返回)
| 字段 | 类型 | 说明 |
|---|---|---|
success | boolean | 是否成功 |
msg | string | 结果信息,如 打印成功 |
data | object | 成功时的附加数据:msg、templateId、replyId、url(toNet 为 true 时)、buffer(buffer 为 true 时) |
# html 打印
curl -X POST http://localhost:7071/controller/printer/print \
-H "Content-Type: application/json" \
-d '{
"printer": "XP-58",
"html": "<html><body><h1>订单打印</h1></body></html>",
"silent": true,
"printBackground": true
}'
# 网络 pdf 打印
curl -X POST http://localhost:7071/controller/printer/print \
-H "Content-Type: application/json" \
-d '{"type": "url_pdf", "pdf_path": "http://example.com/files/invoice.pdf"}'const res = await axios.post('http://localhost:7071/controller/printer/print', {
// 模板打印:模板 JSON 对象
template: { panels: [{ width: 100, height: 60, printElements: [] }] },
templateId: 'tpl-order-001',
silent: true,
});
console.log(res.data); // { success: true, msg: '打印成功', data: {...} }提示
打印任务按打印机排队执行,HTTP 调用会等待任务出队后返回结果。渲染相关失败(如打印机被禁用、窗口销毁)会以 success: false 与 msg 返回。
printer/clientsCount 客户端连接数量
- 方法+路径:
GET /controller/printer/clientsCount - 参数:无
- 返回:
| 字段 | 类型 | 说明 |
|---|---|---|
socketCount | number | Socket.IO 连接数 |
mqttCount | number | MQTT 连接数 |
total | number | 两者之和 |
curl http://localhost:7071/controller/printer/clientsCountprinter/clients 客户端连接信息
- 方法+路径:
GET /controller/printer/clients - 参数:无
- 返回:
| 字段 | 类型 | 说明 |
|---|---|---|
clients | array | 已连接的 Socket.IO 客户端(含连接时携带的 data 与 rooms) |
mqttClients | array | 已连接的 MQTT 客户端列表 |
curl http://localhost:7071/controller/printer/clientsapp 接口
app/baseInfo 应用基础信息
- 方法+路径:
GET /controller/app/baseInfo - 参数:无
- 返回:
AppInfo
| 字段 | 类型 | 说明 |
|---|---|---|
name / version | string | 应用名称、版本号 |
machineId | string | 设备 ID |
id | string | 客户端唯一 ID(持久化) |
mac / ip / ipv6 | string | 网络信息 |
isProd | boolean | 是否生产环境 |
appPath / extraResPath / configPath | string | 应用路径、资源目录、配置文件路径 |
const res = await fetch(`${httpUrl}/controller/app/baseInfo`);
const info = await res.json();app/config 获取配置
- 方法+路径:
GET /controller/app/config - 参数:无
- 返回:完整配置对象(
SchemaType),包含port、token、httpPort、authKey、defaultPrinter、disabledPrinterNames、templateList等全部配置项,以及defaultPrintViewPath等客户端补充的默认路径字段。
curl http://localhost:7071/controller/app/configapp/updateConfig 更新配置
- 方法+路径:
POST /controller/app/updateConfig - 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
config | object | 是 | 新配置,一般传入"当前配置 + 修改项"的完整对象 |
refreshConfig | object | 否 | 修改后需要重启的服务 |
refreshConfig 可选字段(均为 boolean):
| 字段 | 说明 |
|---|---|
socket | 重启 Socket.IO 服务(修改 port/token 后需要) |
cloud | 重连中转/云服务(修改 connectTransit/transitUrl/transitToken 后需要) |
cloudPrint | 重连云打印 SaaS 服务(修改 connectCloud/cloudUrl/cloudToken 后需要) |
mqtt | 重启 MQTT 服务 |
printer | 重建打印窗口(修改 authKey、defaultPrinter、打印窗口路径等后需要) |
window | 刷新主窗口任务栏显示 |
- 返回:更新后的完整配置对象。
// 修改 authKey:必须传 refreshConfig.printer = true,否则渲染服务不重启,水印不会移除
const config = await fetch('http://localhost:7071/controller/app/config').then((r) => r.json());
await fetch('http://localhost:7071/controller/app/updateConfig', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
config: { ...config, authKey: '你的项目授权key' },
refreshConfig: { printer: true },
}),
});app/relaunch 重启客户端
- 方法+路径:
GET /controller/app/relaunch - 参数:无。返回:无(应用重启,连接中断)。
app/openConfig / importConfig / exportConfig 配置文件操作
- 方法+路径:
GET /controller/app/openConfig:用系统编辑器打开配置文件,返回true。GET /controller/app/importConfig:弹出系统文件选择框导入配置,返回true/false。GET /controller/app/exportConfig:弹出系统保存框导出配置,返回true。
- 说明:三个接口会唤起客户端 GUI 交互,适合本地脚本或运维场景,不适合无人值守调用。
app/loadConfigOrRenderer 导入配置/渲染文件
- 方法+路径:
POST /controller/app/loadConfigOrRenderer - 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
fileList | array | 是 | 文件列表,元素:{ name, type, buffer } |
type支持application/json(配置文件,导入后自动更新配置并按需重启相关服务)与application/zip、application/rar(自定义渲染包,解压安装)。- 返回:成功
true;失败{ message }。
app/getTemplate 本地模板列表
- 方法+路径:
GET /controller/app/getTemplate - 参数:无
- 返回:
LocalTemplate[]:{ tempId, url, name, desc, template, testData }。
app/saveTemplate 保存模板
- 方法+路径:
POST /controller/app/saveTemplate - 参数:
LocalTemplate对象整体作为请求体:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
tempId | string | 是 | 模板 id,存在则更新 |
name / desc | string | 否 | 名称、描述 |
url | string | 否 | 模板缩略图;为 base64 图片时自动保存并替换为静态资源地址 |
template | string | 是 | 模板 JSON 字符串 |
testData | string | 否 | 测试数据 |
- 返回:boolean。
curl -X POST http://localhost:7071/controller/app/saveTemplate \
-H "Content-Type: application/json" \
-d '{"tempId":"tpl-001","name":"出库单","template":"{\"panels\":[]}"}'app/deleteTemplate 删除模板
- 方法+路径:
POST /controller/app/deleteTemplate - 参数:
tempId(string) - 返回:boolean。
- 注意:HTTP 通道下请求体整体作为第一个实参传入,该方法未做解构取参,
tempId无法正确命中,HTTP 调用始终返回false。该接口主要供客户端界面(IPC 通道)使用。
app/print 执行打印
- 方法+路径:
POST /controller/app/print - 参数与返回:同
printer/print接口。
app/checkCustomUpdate / downloadCustom / installCustom 自定义渲染更新
- 方法+路径:
GET /controller/app/checkCustomUpdate:检查自定义渲染新版本。有新版本时返回{ localVersion, version, title, url, desc, force },否则返回false(功能关闭时同样返回false)。POST /controller/app/downloadCustom:参数{ version, url },后台下载渲染包,无返回值(下载状态通过客户端窗口内部事件通知)。POST /controller/app/installCustom:参数{ version, url },安装渲染包。
app/openDesignerUrl 打开在线设计器
- 方法+路径:
POST /controller/app/openDesignerUrl - 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 是 | 设计器地址,非 http/https 时按本地设计器处理 |
data | any | 否 | 注入到设计器窗口的设计数据 |
- 返回:成功打开新窗口返回
true(受配置newWindowOpenDesigner控制);失败false。
app/checkUpdate / downloadApp / installApp 应用内更新
- 方法+路径:
GET /controller/app/checkUpdate:检查新版本(受enableAutoUpdater、autoUpdaterUrl配置控制)。GET /controller/app/downloadApp:下载新版本。GET /controller/app/installApp:安装新版本并重启。
- 返回:无(更新进度通过客户端窗口事件展示)。
app/windowMinimize / toggleMaximize / windowMaximize / windowClose 主窗口控制
- 方法+路径:
GET /controller/app/windowMinimize:隐藏主窗口(不在任务栏/dock 显示)。GET /controller/app/toggleMaximize:最大化/还原切换。POST /controller/app/windowMaximize:按参数max(boolean)最大化或还原。HTTP 通道下请求体整体作为第一个实参,恒为真值,实际只会执行最大化,主要供客户端界面使用。GET /controller/app/windowClose:关闭窗口不退出应用(showInTaskbar为 true 时最小化到任务栏,否则隐藏到托盘)。
log 接口
log/printLogList 打印日志列表
- 方法+路径:
POST /controller/log/printLogList - 参数:
QueryData(SQLite 查询条件直接拼接,仅建议在可信环境使用):
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
condition | string[] | 是 | SQL WHERE 片段数组,多个用 AND 连接,占位符用 ? |
params | string[] | 是 | 条件对应的参数值 |
page | object | 是 | { currentPage, pageSize },页码从 1 开始 |
sort | object | 是 | { prop, order },如 { prop: 'timestamp', order: 'desc' } |
- 返回:
| 字段 | 类型 | 说明 |
|---|---|---|
total | number | 总条数 |
list | array | 日志数组,元素:id、timestamp、printer、printType、clientType、data(打印参数 JSON 字符串)、pageNum、status(success/failure)、errorMessage |
curl -X POST http://localhost:7071/controller/log/printLogList \
-H "Content-Type: application/json" \
-d '{
"condition": ["timestamp >= ? AND timestamp < ?"],
"params": ["2026-08-03", "2026-08-11"],
"page": { "currentPage": 1, "pageSize": 20 },
"sort": { "prop": "timestamp", "order": "desc" }
}'const res = await axios.post('http://localhost:7071/controller/log/printLogList', {
condition: [],
params: [],
page: { currentPage: 1, pageSize: 20 },
sort: { prop: 'timestamp', order: 'desc' },
});
console.log(res.data.total, res.data.list);log/rePrint 重新打印
- 方法+路径:
POST /controller/log/rePrint - 参数:
EventData打印事件对象(一般取自printLogList返回的data字段反序列化后的内容),服务端会标记rePrint: true后走完整打印流程。 - 返回:
TaskResult(同printer/print)。
const log = logs.list[0];
const res = await axios.post('http://localhost:7071/controller/log/rePrint', JSON.parse(log.data));log/preview 预览打印数据
- 方法+路径:
POST /controller/log/preview - 参数:
{ id }(string,打印日志 id) - 返回:日志存在时打开预览窗口并发送打印数据(Electron 窗口对象经 JSON 序列化后为空对象);日志不存在返回
false。 - 说明:会弹出客户端预览窗口,适合本地或带界面的场景。
版权所有
版权归属:sv-print
