常规通过小程序或APP在外出时控制本地电脑实现打印功能,可以结合远程桌面技术、云打印服务或开发定制化的远程打印解决方案。
但这里我们采用自已的实现方案来解决

服务器端实现
搭建一个后端socket服务,监听来自手机的打印请求。监听到打印任务后向本地客户端打印机发送打印命令。
手机端小程序APP
开发小程序或APP,通过API与本地电脑的后端服务通信。
用户选择文件后,将文件上传或发送打印指令到后端服务。
本地客户端打印执行
本地客户端进行socket连接,注册服务。后端服务接收到打印请求后进行打印。本地客户端我们采用的是electron来连接服务器端socket。本地客户端就可以静默打印。客户端核心方案的打印代码是采用了electron BrowserWindow静默打印实现。
win = new BrowserWindow({
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: join(__dirname, '../preload/print.js')
}
})
if (options.printType === 'pdf') {
// PDF打印 - 直接加载URL
if (!options.url) {
throw new Error('URL is required for PDF printing')
}
await win.loadURL(options.url)
} else {
// HTML内容打印 - 加载模板并注入内容
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
await win.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/print.html`)
} else {
await win.loadFile(join(__dirname, '../renderer/print.html'))
}
// 检查并注入HTML内容
if (!options.content && !options.url) {
throw new Error('Either content or url is required for HTML printing')
}
let htmlContent = options.content
if (!htmlContent && options.url) {
// 如果提供了url但没有content,尝试从 url 解析内容
htmlContent = decodeURIComponent(
options.url.replace('data:text/html;charset=utf-8,', '')
)
}
await win.webContents.executeJavaScript(`
document.getElementById('printContent').innerHTML = ${JSON.stringify(htmlContent)}
`)
}
// 等待内容加载完成
await new Promise((resolve) => setTimeout(resolve, 1000))
await win.webContents.executeJavaScript('document.readyState === "complete"')
// 执行打印
const result = await new Promise((resolve, reject) => {
win.webContents.print(
{
silent: true,
printBackground: options.printBackground || true,
deviceName: options.printer,
pageSize: options.pageSize === 'custom'
? {
width: options.customWidth * 1000,
height: options.customHeight * 1000
}
: options.pageSize,
landscape: options.landscape,
copies: options.copies || 1,
margins: {
top: options.margins?.top || 0,
bottom: options.margins?.bottom || 0,
left: options.margins?.left || 0,
right: options.margins?.right || 0
}
},
(success, failureError) => {
if (success) {
resolve({ success: true })
} else {
reject(failureError || new Error('Print failed'))
}
}
)
})
win.close()
优点
完全自定义,满足特定需求。
数据传输更安全,隐私可控。
缺点
开发成本较高,需要一定的技术能力。
需要确保本地电脑和手机在同一网络下,或通过公网IP访问。