| Crates.io | tauri-plugin-printer-wkhtml-bin |
| lib.rs | tauri-plugin-printer-wkhtml-bin |
| version | 0.1.3 |
| created_at | 2025-11-13 17:00:15.860479+00 |
| updated_at | 2025-11-14 11:10:28.103599+00 |
| description | Tauri plugin for printer with embedded wkhtmltopdf for Windows |
| homepage | |
| repository | https://github.com/FrancoJFerreyra/tauri-plugin-printer |
| max_upload_size | |
| id | 1931532 |
| size | 13,805,108 |
A powerful Tauri V2 printer plugin
Supports PDF/HTML printing, printer management, print job control, and more.
Important: Make sure to place the wkhtmltopdf.exe binary inside the src-tauri/bin folder of your project. The plugin will automatically look for it there.
Install the plugin
cargo add tauri-plugin-printer-wkhtml-bin
npm i tauri-plugin-printer-wkhtml-bin
Register the plugin
// src-tauri/src/lib.rs
use tauri_plugin_printer_wkhtml_bin::init;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Configure permissions
// src-tauri/capabilities/default.json
{
"permissions": [
"printer-wkhtml-bin:allow-get-printers",
"printer-wkhtml-bin:allow-print-pdf",
"printer-wkhtml-bin:allow-print-html"
]
}
Start using
import { getPrinters, printPdf } from 'tauri-plugin-printer-wkhtml-bin';
// Get printers
const printers = JSON.parse(await getPrinters());
console.log('Available printers:', printers);
// Print PDF
await printPdf({
path: '/path/to/document.pdf',
printer: printers[0].name
});
🎉 Congratulations! You have successfully integrated the printer plugin and can now start printing documents.
This project is based on the following open source projects:
Thanks to the original authors for their contributions and open source spirit.
wkhtmltopdf in bin folder inside src-tauriImportant: Make sure to place the wkhtmltopdf.exe binary inside the src-tauri/bin folder of your project. The plugin will automatically look for it there.
# Add Rust dependency
cargo add tauri-plugin-printer-wkhtml-bin
# Install frontend API
npm i tauri-plugin-printer-wkhtml-bin
npx tauri add https://github.com/FrancoJFerreyra/tauri-plugin-printer
Cargo.toml:[dependencies]
tauri-plugin-printer-wkhtml-bin = "0.1.3"
# Or use Git version
# tauri-plugin-printer-wkhtml-bin = { git = "https://github.com/FrancoJFerreyra/tauri-plugin-printer" }
src-tauri/src/lib.rs:use tauri_plugin_printer_wkhtml_bin::init;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
src-tauri/capabilities/default.json:{
"permissions": [
"printer-wkhtml-bin:default"
]
}
npm i tauri-plugin-printer-wkhtml-bin
import { ping, getPrinters } from 'tauri-plugin-printer-wkhtml-bin';
// Test plugin connection
const response = await ping({ value: 'Hello from frontend!' });
console.log(response);
// Get printer list
const printers = await getPrinters();
console.log('Available printers:', printers);
import {
ping,
getPrinters,
getPrintersByName,
printPdf,
printHtml,
getJobs,
getJobsById,
resumeJob,
restartJob,
pauseJob,
removeJob
} from 'tauri-plugin-printer-wkhtml-bin';
// 1. Get all printers
const allPrinters = await getPrinters();
// 2. Get specific printer by name
const specificPrinter = await getPrintersByName('Microsoft Print to PDF');
// 3. Print PDF file
const printResult = await printPdf({
path: '/path/to/your/file.pdf',
printer: 'Microsoft Print to PDF',
pages: '1-3',
subset: 'odd'
});
// 4. Print HTML content
const htmlPrintResult = await printHtml({
html: '<h1>Hello World</h1><p>This is a HTML print test</p>',
printer: 'Microsoft Print to PDF'
});
// 5. Get print jobs
const jobs = await getJobs('Microsoft Print to PDF');
// 6. Manage print jobs
const jobId = '123';
const printerName = 'Microsoft Print to PDF';
// Pause job
await pauseJob(printerName, jobId);
// Resume job
await resumeJob(printerName, jobId);
// Restart job
await restartJob(printerName, jobId);
// Remove job
await removeJob(printerName, jobId);
import { printHtml, getPrinters } from 'tauri-plugin-printer-wkhtml-bin';
// Generate invoice HTML
const invoiceHtml = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Invoice</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { text-align: center; margin-bottom: 30px; }
.invoice-details { margin-bottom: 20px; }
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<div class="header">
<h1>Invoice</h1>
<p>Invoice No: INV-2024-001</p>
</div>
<div class="invoice-details">
<p><strong>Customer:</strong> Zhang San</p>
<p><strong>Date:</strong> 2024-01-15</p>
</div>
<table>
<tr><th>Item</th><th>Qty</th><th>Price</th><th>Total</th></tr>
<tr><td>Product A</td><td>2</td><td>¥100</td><td>¥200</td></tr>
<tr><td>Product B</td><td>1</td><td>¥150</td><td>¥150</td></tr>
</table>
<p style="text-align: right; margin-top: 20px;"><strong>total: ¥350</strong></p>
</body>
</html>
`;
// Print invoice
try {
const result = await printHtml({
html: invoiceHtml,
printer: 'Microsoft Print to PDF' // Or choose another printer
});
console.log('Invoice printed successfully:', result);
} catch (error) {
console.error('Printing failed:', error);
}
import { printPdf, getPrinters } from 'tauri-plugin-printer-wkhtml-bin';
const pdfFiles = [
'/path/to/document1.pdf',
'/path/to/document2.pdf',
'/path/to/document3.pdf'
];
// Get default printer
const printers = JSON.parse(await getPrinters());
const defaultPrinter = printers.find(p => p.is_default)?.name || printers[0]?.name;
// Batch print
for (const filePath of pdfFiles) {
try {
await printPdf({
path: filePath,
printer: defaultPrinter,
pages: '1-10' // Print only the first 10 pages
});
console.log(`Printed: ${filePath}`);
} catch (error) {
console.error(`Print failed ${filePath}:`, error);
}
}
import { getPrinters, getJobs } from 'tauri-plugin-printer-wkhtml-bin';
// Monitor printer status
async function monitorPrinters() {
try {
const printers = JSON.parse(await getPrinters());
for (const printer of printers) {
console.log(`Printer: ${printer.name}`);
console.log(`Status: ${printer.status}`);
console.log(`Default: ${printer.is_default ? 'Yes' : 'No'}`);
// Get print jobs
const jobs = JSON.parse(await getJobs(printer.name));
console.log(`Pending jobs: ${jobs.length}`);
console.log('---');
}
} catch (error) {
console.error('Failed to get printer info:', error);
}
}
// Check every 30 seconds
setInterval(monitorPrinters, 30000);
ping(request: PingRequest): Promise<PingResponse>Test plugin connection status.
getPrinters(): Promise<string>Get all available printers in the system, returned as a JSON string.
getPrintersByName(name: string): Promise<string>Get info of a specific printer by name.
printPdf(options: PrintOptions): Promise<string>Print PDF files.
PrintOptions parameters:
path: PDF file pathprinter: Printer namepages: Page range (optional)subset: Page subset (optional)printHtml(options: HtmlPrintOptions): Promise<string>Print HTML content.
HtmlPrintOptions parameters:
html: HTML content stringprinter: Printer namegetJobs(printer: string): Promise<string> - Get all jobs for a printergetJobsById(printer: string, jobId: string): Promise<string> - Get info for a specific jobpauseJob(printer: string, jobId: string): Promise<string> - Pause a print jobresumeJob(printer: string, jobId: string): Promise<string> - Resume a print jobrestartJob(printer: string, jobId: string): Promise<string> - Restart a print jobremoveJob(printer: string, jobId: string): Promise<string> - Delete a print job# Clone repository
git clone https://github.com/FrancoJFerreyra/tauri-plugin-printer.git
cd tauri-plugin-printer
# Build plugin
npm run build
# Run example app
cd examples/tauri-app
npm install
npm run tauri:dev
tauri-plugin-printer/
├── src/ # Rust source code
│ ├── lib.rs # Main plugin entrypoint
│ ├── commands.rs # Tauri command definitions
│ ├── desktop.rs # Desktop implementation
│ ├── windows.rs # Windows specific implementation
│ └── ...
├── guest-js/ # JavaScript API
│ └── index.ts # Frontend API definition
├── permissions/ # Permission config
├── examples/ # Sample apps
│ └── tauri-app/ # Vue.js example
└── dist-js/ # Built JS files
The plugin uses the following permissions:
[default]
description = "Default permissions for the plugin"
permissions = [
"allow-ping",
"allow-create-temp-file",
"allow-remove-temp-file",
"allow-get-printers",
"allow-get-printers-by-name",
"allow-print-pdf",
"allow-print-html",
"allow-get-jobs",
"allow-get-jobs-by-id",
"allow-resume-job",
"allow-restart-job",
"allow-pause-job",
"allow-remove-job"
]
A: Check:
A: Possible solutions:
A: Suggestions:
A: Ensure configuration in src-tauri/capabilities/default.json:
{
"permissions": [
"printer-wkhtml-bin:allow-ping",
"printer-wkhtml-bin:allow-get-printers",
"printer-wkhtml-bin:allow-get-printers-by-name",
"printer-wkhtml-bin:allow-print-pdf",
"printer-wkhtml-bin:allow-print-html",
"printer-wkhtml-bin:allow-get-jobs",
"printer-wkhtml-bin:allow-restart-job",
"printer-wkhtml-bin:allow-pause-job",
"printer-wkhtml-bin:allow-resume-job",
"printer-wkhtml-bin:allow-remove-job"
]
}
Enable detailed logs:
RUST_LOG=debug npm run tauri dev
Check printer status:
const printers = JSON.parse(await getPrinters());
console.log('Available printers:', printers);
Test connection:
try {
const result = await ping();
console.log('Plugin connected:', result);
} catch (error) {
console.error('Plugin connection failed:', error);
}
// For large PDF files, suggest printing by page batches
const largePdfPath = '/path/to/large-document.pdf';
// Print in batches, 10 pages each time
for (let startPage = 1; startPage <= totalPages; startPage += 10) {
const endPage = Math.min(startPage + 9, totalPages);
await printPdf({
path: largePdfPath,
printer: printerName,
pages: `${startPage}-${endPage}`
});
// Add delay to avoid overloading the print queue
await new Promise(resolve => setTimeout(resolve, 1000));
}
// Optimized HTML structure
const optimizedHtml = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
/* Print styles */
@media print {
body { margin: 0; padding: 20px; }
.no-print { display: none; }
.page-break { page-break-before: always; }
}
/* Basic style */
body {
font-family: 'Arial', sans-serif;
font-size: 12pt;
line-height: 1.4;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
th, td {
border: 1px solid #000;
padding: 8px;
text-align: left;
}
</style>
</head>
<body>
<!-- Content -->
</body>
</html>
`;
// Print function with retry logic
async function printWithRetry(printFunction, options, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const result = await printFunction(options);
return result;
} catch (error) {
console.warn(`Print attempt ${attempt} failed:`, error.message);
if (attempt === maxRetries) {
throw new Error(`Print failed after ${maxRetries} retries: ${error.message}`);
}
// Exponential backoff delay
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
// Usage
try {
await printWithRetry(printPdf, {
path: '/path/to/document.pdf',
printer: 'HP LaserJet'
});
} catch (error) {
console.error('Final print failed:', error);
}
class PrintQueue {
constructor(maxConcurrent = 2) {
this.queue = [];
this.running = [];
this.maxConcurrent = maxConcurrent;
}
async add(printTask) {
return new Promise((resolve, reject) => {
this.queue.push({ task: printTask, resolve, reject });
this.process();
});
}
async process() {
if (this.running.length >= this.maxConcurrent || this.queue.length === 0) {
return;
}
const { task, resolve, reject } = this.queue.shift();
const promise = task().then(resolve).catch(reject);
this.running.push(promise);
promise.finally(() => {
this.running = this.running.filter(p => p !== promise);
this.process();
});
}
}
// Using the print queue
const printQueue = new PrintQueue(2); // up to 2 concurrent print jobs
// Add print tasks
const files = ['file1.pdf', 'file2.pdf', 'file3.pdf'];
for (const file of files) {
printQueue.add(() => printPdf({ path: file, printer: 'Default' }));
}
Issues and Pull Requests are welcome!
MIT License
This project is based on:
Thanks to the original authors!
wkhtmltopdf in the bin folder inside src-tauri