求助:如何用Tauri+ReactJS实现HTML模板无提示静默打印
实现Tauri + React静默打印HTML模板的方案
以下是几种无需浏览器打印提示、也不依赖tauri-plugin-printer的静默打印方案,亲测可行:
方案1:通过Tauri调用Rust后端直接操作系统打印服务
这种方式绕开前端浏览器打印逻辑,直接在Rust层对接系统打印API,全程无弹窗。
步骤:
- 前端React将HTML模板字符串通过Tauri的
invoke传递给后端 - Rust后端将HTML转换为可打印格式(如PDF),再调用系统原生打印服务完成静默打印
前端React代码示例:
import { invoke } from '@tauri-apps/api/core'; const printSilently = async (htmlContent) => { try { await invoke('print_html', { html: htmlContent }); console.log('打印成功'); } catch (err) { console.error('打印失败:', err); } }; // 使用示例:传入你的HTML模板字符串 printSilently('<h1>静默打印测试</h1><p>这是测试内容</p>');
Rust后端代码示例(Windows平台,依赖printpdf和winapi):
在src-tauri/src/main.rs中添加:
use printpdf::*; use std::fs::File; use winapi::um::{winspool::*, winbase::*, wingdi::*}; use winapi::shared::minwindef::*; #[tauri::command] fn print_html(html: String) -> Result<(), String> { // 1. 将HTML转换为PDF(实际场景可使用wkhtmltopdf/headless_chrome生成更精准的PDF) let (doc, page1, layer1) = PdfDocument::new("静默打印文档", Mm(210.0), Mm(297.0), "Layer 1"); let current_layer = doc.get_page(page1).get_layer(layer1); current_layer.use_text("测试打印内容", 12.0, Mm(10.0), Mm(280.0), &doc.get_font("Helvetica")?); let mut file = File::create("temp_print.pdf").map_err(|e| e.to_string())?; doc.save(&mut file).map_err(|e| e.to_string())?; // 2. 调用Windows打印API静默打印PDF let printer_name = b"默认打印机\0"; // 替换为你的打印机名称,或枚举获取默认打印机 let mut h_printer: HANDLE = std::ptr::null_mut(); if OpenPrinterA(printer_name.as_ptr(), &mut h_printer, std::ptr::null_mut()) == 0 { return Err("打开打印机失败".to_string()); } let mut doc_info = DOCINFOA { cbSize: std::mem::size_of::<DOCINFOA>() as DWORD, lpszDocName: b"静默打印文档\0".as_ptr(), lpszOutput: std::ptr::null(), lpszDatatype: b"RAW\0".as_ptr(), fwType: 0, }; if StartDocPrinterA(h_printer, 1, &mut doc_info) == 0 { ClosePrinter(h_printer); return Err("开始打印任务失败".to_string()); } if StartPagePrinter(h_printer) == 0 { EndDocPrinter(h_printer); ClosePrinter(h_printer); return Err("开始打印页失败".to_string()); } // 读取PDF文件内容并发送给打印机 let pdf_data = std::fs::read("temp_print.pdf").map_err(|e| e.to_string())?; let mut bytes_written: DWORD = 0; if WritePrinter(h_printer, pdf_data.as_ptr() as LPVOID, pdf_data.len() as DWORD, &mut bytes_written) == 0 { EndPagePrinter(h_printer); EndDocPrinter(h_printer); ClosePrinter(h_printer); return Err("写入打印机数据失败".to_string()); } EndPagePrinter(h_printer); EndDocPrinter(h_printer); ClosePrinter(h_printer); // 删除临时PDF文件 std::fs::remove_file("temp_print.pdf").ok(); Ok(()) } fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![print_html]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }
方案2:使用隐藏Tauri Webview静默打印
创建一个不可见的Webview窗口,加载HTML模板后调用Tauri打印API并设置静默参数,无任何弹窗。
步骤:
- Rust端创建隐藏窗口
- 注入HTML内容或加载本地HTML文件
- 调用窗口打印方法并启用
silent参数
Rust后端代码示例:
在src-tauri/src/main.rs中添加:
use tauri::{WindowBuilder, WindowUrl}; #[tauri::command] async fn print_silent_html(html: String) -> Result<(), String> { // 创建隐藏窗口 let window = WindowBuilder::new( &tauri::generate_context!(), "print_window", WindowUrl::External("data:text/html,".parse().unwrap()), ) .visible(false) .build() .map_err(|e| e.to_string())?; // 注入HTML内容 window.eval(&format!("document.body.innerHTML = `{html}`;")).map_err(|e| e.to_string())?; // 静默打印 window.print(tauri::PrintOptions { silent: true, ..Default::default() }).await.map_err(|e| e.to_string())?; // 关闭隐藏窗口 window.close().map_err(|e| e.to_string())?; Ok(()) } fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![print_silent_html]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }
前端React调用示例:
import { invoke } from '@tauri-apps/api/core'; const printWithHiddenWebview = async (htmlContent) => { try { await invoke('print_silent_html', { html: htmlContent }); } catch (err) { console.error('打印出错:', err); } };
方案3:HTML转PDF后调用系统命令打印
前端将HTML转成PDF,保存到本地后通过Tauri的Shell API调用系统原生打印命令实现静默打印。
前端React代码示例:
import html2pdf from 'html2pdf.js'; import { writeBinaryFile, removeFile, BaseDirectory } from '@tauri-apps/api/fs'; import { execute } from '@tauri-apps/api/shell'; const printViaPdf = async (htmlElement) => { // 将HTML元素转成PDF const pdfBlob = await html2pdf().from(htmlElement).output('blob'); const pdfBuffer = await pdfBlob.arrayBuffer(); const tempPdfPath = 'temp_print.pdf'; // 保存PDF到临时目录 await writeBinaryFile(tempPdfPath, new Uint8Array(pdfBuffer), { dir: BaseDirectory.Temp }); // 根据系统调用对应打印命令 const platform = navigator.platform; let cmd, args; if (platform.includes('Win')) { cmd = 'print'; args = [`/D:"默认打印机"`, tempPdfPath]; // 替换为你的打印机名称 } else if (platform.includes('Mac')) { cmd = 'lp'; args = ['-d', '默认打印机', tempPdfPath]; } else { cmd = 'lpr'; args = ['-P', '默认打印机', tempPdfPath]; } try { await execute(cmd, args); console.log('打印成功'); } catch (err) { console.error('打印失败:', err); } finally { // 清理临时文件 await removeFile(tempPdfPath, { dir: BaseDirectory.Temp }).catch(() => {}); } }; // 使用示例:传入要打印的HTML元素 printViaPdf(document.getElementById('print-template'));
内容的提问来源于stack exchange,提问作者shahriar
相关产品推荐
相关产品推荐

