Tip: Hit and search this page for keywords!!
Introduction
This is a tutorial for web developers to add a web applet to your page capable of sending raw commands to your printer. This is common for Barcodes, Thermal Printing, Point-Of-Sales (POS), and other commercial/industry purposes.
This is possible by using JavaScript to talk to Java through the "Applet" interface that is provided by all major web browsers.
Download and extract a featured version. There's a bunch of files, but we'll primarily be using "sample.html". Also make sure "qz-print.jar" resides in the same folder/location.
https://jzebra.googlecode.com/files/unzip-screenshot.PNG
The sample runs client-side. No uploading to a web server is needed for this tutorial.
There are separate buttons for each type of printing, so study them closely. Behind each button is a small snippet of JavaScript code for interacting with the qz-print applet.
https://jzebra.googlecode.com/files/sample-html.PNG
| Note: qz-print requires Java 5 or higher to run. For help installing Java on your platform, see the Java tutorial. | |:--------------------------------------------------------------------------------------------------------------------------------------------------|
The steps below walk through adding an applet to your web page, and explain how to interact with it through JavaScript.
Steps
Load The Applet
- Make sure your printer is set up on your workstation with the name "zebra" (this can be changed later).
- Make sure printer is connected as a raw print queue for your operating sytem (Click the Windows, Ubuntu, or Mac logo for details)
- Download the latest version and extract the contents to your desktop. Open "sample.html" with a web browser.
- The following applet code creates the applet.
<html><body> <applet id="qz" name="QZ Print Plugin" code="qz.PrintApplet.class" archive="./qz-print.jar" width="100" height="100"></applet><br><br> </html></body>
- The html file should reside in the same folder as
qz-print.jar
. Alternately, you can move the JAR to a different location so long as you changearchive="./qz-print.jar"
to match your new location.| Note: Java 7 + Apache users: Change apache config to use "SSLStrictSNIVHostCheck on" and restart apache. read more here https://bitbucket.org/StrangeWill/redmine-inline-attach-screenshot/issue/17/java-17-unrecognized_name-due-sni-support | |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Note: Chrome users may receive a message "The Java plug-in requires your permission to run". Click "Always run on this site"
http://jzebra.googlecode.com/files/permission.jpg' />
- The following applet code creates the applet.
Note: IE7 may receive an ActiveX warning. Click "Allow Blocked Content"
Note: IE7 may be prompt to Click to Activate This Control each time the applet loads. Click here for details.
- The applet will begin to load in the web page.
Note: Chrome users on Linux with outdated plugins, launch chrome with "
google-chrome --always-authorize-plugins --allow-outdated-plugins
". This will allow Java to load in Chrome without warnings of outdated plugins!http://2.bp.blogspot.com/_9hmP3Ho0t14/SxgoGt3lmKI/AAAAAAAAAXA/jsqVvrlRl4k/s400/applet_loading.PNG
- Next, Java security dialog prompt is shown. Click "Run".
https://jzebra.googlecode.com/files/trusted-warning.PNG
- The applet should be loaded. At this point it will look like a plain html page with a few sample buttons.
https://jzebra.googlecode.com/files/sample-html.PNG
- Right click the Java system tray icon (Windows) and clicking "Open Java Console". Linux Oracle Java users run:
jcontrol
--> Advanced --> Java Console --> Show Console. Linux OpenJDK users, run the web browser from a command line.
Note: The Java Console is critical for calibrating qz-print for your printer.
- You should see the version of qz-print
"INFO: qz-print 1.x.x"
followed by"===== JAVASCRIPT LISTENER THREAD STARTED ====="
in the log. Sample:
Java Plug-in 10.45.2.18
Using JRE version 1.7.0_45-b18 Java HotSpot(TM) Client VM
User home directory = %USERPROFILE%
----------------------------------------------------
c: clear console window
f: finalize objects on finalization queue
g: garbage collect
h: display this help message
l: dump classloader list
m: print memory usage
o: trigger logging
q: hide console
r: reload policy configuration
s: dump system and deployment properties
t: dump thread list
v: dump thread stack
x: clear classloader cache
0-5: set trace level to <n>
----------------------------------------------------
Oct 19, 2013 1:40:05 AM qz.LogIt log
INFO: QZ-PRINT 1.6.8
Oct 19, 2013 1:40:05 AM qz.LogIt log
INFO: ===== JAVASCRIPT LISTENER THREAD STARTED =====
Oct 19, 2013 1:40:09 AM qz.LogIt log
INFO: ===== SEARCHING FOR PRINTER =====
Oct 19, 2013 1:40:10 AM qz.LogIt log
INFO: Found 4 attached printers.
Oct 19, 2013 1:40:10 AM qz.LogIt log
INFO: Printer specified: \QZebra\E
Oct 19, 2013 1:40:10 AM qz.LogIt log
INFO: Printer name match: \\myserver\Zebra LP2844
Oct 19, 2013 1:40:10 AM qz.LogIt log
INFO: Using best match: \\myserver\Zebra LP2844
Oct 19, 2013 1:40:10 AM qz.LogIt log
WARNING: Tried calling JavaScript function "jzebraDoneFindingPrinters" through web browser but it has not been implemented (No such method "jzebraDoneFindingPrinters" on JavaScript object)
CacheEntry[file:/C:/Users/Owner/Desktop/dist/qz-run.jnlp]: updateAvailable=false,lastModified=Sat Oct 19 01:27:44 EDT 2013,length=599
CacheEntry[file:/C:/Users/Owner/Desktop/dist/qz-print.jar]: updateAvailable=false,lastModified=Sat Oct 19 01:27:44 EDT 2013,length=105639
CacheEntry[file:/C:/Users/Owner/Desktop/dist/lib/jssc_qz.jar]: updateAvailable=false,lastModified=Sat Oct 19 01:27:44 EDT 2013,length=158623
CacheEntry[file:/C:/Users/Owner/Desktop/dist/lib/pdf-renderer_qz.jar]: updateAvailable=false,lastModified=Sat Oct 19 01:27:44 EDT 2013,length=1639200
At this point, your applet has now been loaded into the web browser. See Printing section for printer discovery and for sending print commands directly to your printer.
Printing
- qz-print's parameters are set through JavaScript commands.
- First, insert (or modify) the JavaScript code to search for a printer named "zebra". The printer name can be anything you wish, i.e:
"Epson"
,"Citizen"
,"Generic"
,"BOCA"
, etc.
<script>
function findPrinter() {
// Searches for locally installed printer with "zebra" in the name
qz.findPrinter("zebra");
// *Note, to get the default printer, call:
// qz.findPrinter(); // or
// qz.findPrinter(null);
}
</script>
See also
sample.html
, section "findPrinter()". Note: To select another printer, you can also choose it by index usingapplet.setPrinter(index);
- Second, use html code for a Find Printer button using standard HTML input button. This button has already been provided in
sample.html
.
<input type=button onClick="findPrinter()" value="Detect Printer"><br><br>
- Third, test the Find Printer button.
- Load page in web browser and click "Find Printer" button.
- View Java console for output. Look for
"INFO: Printer found..."
- TODO: Find Printer Button Screenshot
- Load page in web browser and click "Find Printer" button.
- Fourth, insert (or modify) this JavaScript code to send commands to printer. This button has already been provided in
sample.html
.
- JavaScript Code: (Example)
function print() {
// Send characters/raw commands to applet using "append"
// Hint: Carriage Return = \r, New Line = \n, Escape Double Quotes= \"
qz.append("A37,503,0,1,2,3,N,QZ-PRINT TEST PRINT\n");
// Send characters/raw commands to printer
qz.print();
}
See also
sample.html
, section "print()".
Note: The raw commands provided in the sample are not intended for use with your printer, they're provided as an example.
- JavaScript Code: (Example)
- Next, add html code for a Print button. This button has already been provided in
sample.html
.
<input type=button onClick="print()" value="Print"><br><br>
- Last, test "print.html"
- Load page in web browser and click "Find Printer" button
- Click "Print" button
- TODO: Print Button Screenshot
- TODO: Console Output Screenshot
- View Java console for output
- Load page in web browser and click "Find Printer" button
- If problems exist, try the included sample.html or email the author.
php Printing
- If you would rather use php, replace
print()
function with this code:
function print() {
// Uses the php `"echo"` function in conjunction with qz-print `"append"` function
// This assumes you have already assigned a value to `"$commands"` with php
qz.append(<?php echo $commands; ?>);
// Send characters/raw commands to printer
qz.print();
}
Base64 Printing
- Note: For Base64 image printing, see TutorialWebApplet#Printing_Images
- If print data is base64 encoded, replace
print()
function with this code: (Note: Versions 1.4.1 & 1.4.2 have a bug, see Issue 73.)
// Use qz-print's `"append64"` function. This will automatically convert provided
// base64 encoded text into ascii/bytes, etc.
function print() {
qz.append64("SEVMTE8hICBZT1UgQVJFIFJFQURJTkcgQSBERUNPREVE");
qz.append64("IEJBU0U2NCBNRVNTQUdFIFNFTlQgRlJPTSBKWkVCUkEu");
// Send characters/raw commands to printer
qz.print();
}
See also
sample.html
, section "print()".
Epson/Citizen ESC/P Printing
Note: See ESCPCommands for many more examples
- Optional CHR() function for easier reading
function chr(i) {
return String.fromCharCode(i);
}
- Open cash drawer (usually connected to printer via cable)
function openCashDrawer() {
qz.append(chr(27) + "\x70" + "\x30" + chr(25) + chr(25) + "\r");
qz.print();
}
- Cut paper
function cutPaper() {
qz.append(chr(27) + chr(105)); // cut paper
}
- Basic font styling
function boldAndCenter() {
qz.append(chr(27) + chr(69) + "\r"); // bold on
qz.append(chr(27) + "\x61" + "\x31"); // center justify
}
- Print Image (Still experimental, needs testing)
See TutorialWebApplet#Printing_Images
Printing Special Characters
- If special ascii, chr, hex or escape characters need to be printed, use the char code, or the "\x" notation. Note, the "NUL" character, or "\x00" is not supported in JavaScript, so appendHex() is needed.
function print() {
// Appends CHR(27) + CHR(29) using `"fromCharCode"` function
qz.append(String.fromCharCode(27) + String.fromCharCode(29));
// Appends hexadecimal data
qz.appendHex("x00x01x02xFF");
// Send characters/raw commands to printer
qz.print();
}
See also
sample.html
, section "print()".
See also Issue 28// Force special DOS/Win characters on UNIX/Linux
qz.setEncoding("cp866"); // or
qz.setEncoding("cp1252");
// Force UTF8 characters on Windows
qz.setEncoding("UTF-8");
// Force MS/DOS Western Europe (i.e. "Maçã")
qz.setEncoding("850");
See also Issue 61, which also prevents append("\x00") from working. (Using appendHex() fixes this or many choose to use use Base64 encoded print commands// Submitted via Simon on mailing list jzebra-users@googlegroups.com
// Print GBP '£' sign using ESC/P
// First change code page to UK
qz.appendHex("x1Bx52x03");
// Then just use '#' where you want your E
qz.append("#5.00");
Advanced Print Spooling
- Since version 1.0.6, qz-print has the ability to control spooling to the printer. This feature allows to print in batches of 5, 10, etc. This has advantages due to buffer limitation on certain printer models where submitting 100+ labels randomly stop in the middle of printing. In addition, some programmers have had success with using it for easier reprints.
function print() {
// Mark the end of a label, in this case P1 plus a newline character
// qz-printknows to look for this and treat this as the end of a "page"
// for better control of larger spooled jobs (i.e. 50+ labels)
qz.setEndOfDocument("P1\n");
// The amount of labels to spool to the printer at a time. When
// qz-print counts this many `EndOfDocument`'s, a new print job will
// automatically be spooled to the printer and counting will start
// over.
qz.setDocumentsPerSpool("10");
// Send characters/raw commands to printer
qz.print();
}
See also sample.html
, section "printPages()".
File Printing
- This feature allows a raw file to be spooled directly to the printer
function printFile() {
if (qz != null) {
// Using qz-print's "appendFile()" function, a file containg your raw EPL/ZPL
// can be sent directly to the printer
// Example:
// qz.appendFile("http://yoursite/zpllabel.txt"); // ...etc
qz.appendFile(window.location.href + "/../zpl.txt");
qz.print();
}
}
XML Printing
- Since version 1.0.8, qz-print has the ability to read the contents of an XML file containing Base64 encoded commands and send these commands to the printer. The function requires two parameters, the URL of the XML file and the tagname containing the Base64 encoded text.
function printXML() {
// Appends the contents of an XML file from a SOAP response, etc.
// a valid relative URL or a valid complete URL is required for the XML
// file. The second parameter must be a valid XML tag/node containing
// base64 encoded data, i.e. <node_1>aGVsbG8gd29ybGQ=</node_1>
// Example:
// qz.appendXML("http://yoursite.com/zpl.xml", "node_1");
qz.appendXML("C:\\zpl.xml", "v7:Image");
// Send characters/raw commands to printer
qz.print();
}
See also sample.html
, section "printXML()".
Print to File
- Since version 1.1.9, qz-print allows printing to a physical file. This is useful for bypassing printer drivers completely and sending raw data to a remote Windows Print Server queue, i.e. \\server\printer. (Thanks André T)
function printToFile() {
// Append some data
qz.append("A37,503,0,1,2,3,N,ABC WIDGET CO\n");
// Note, the doubly escaped forward slashes!
qz.printToFile("\\\\server\\printer")
}
PDF Printing
- Since version 1.1.9, qz-print allows printing PDF files directly to a printer. This functionality is experimental and uses a 3rd party renderer "PDF-RENDERER". This feature will not work with many raw printing devices, such as Zebra, Epson, Citizen printers. The data is sent in PostScript format, which is more common for LaserJet printers. USE WITH CAUTION!
function printPDF() {
// Make sure pdf-renderer.jar is in the "./lib" folder
// Append the PDF
qz.appendPDF(window.location.href + "/../sample.pdf");
// Very important for PDFs, use "printPS()" instead of "print()"
qz.printPS();
}
Note: If printing dynamically generated PDF from php, make sure to add header
'Content-Type: application/pdf'
as well as'Content-Disposition:inline;filename=example.pdf'
or else PDF-RENDERER plugin will throw an error: "Exception occurred: This may not be a PDF File". See Issue 48 for more details CUPS/Linux PDF Printing: Please note, there is a bug preventing margins from working properly on some versions of CUPS: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6726691
Printing Images
- Experimental support for appending printer-specific images by url and/or Base64.
// *Note 1: Applet will append special raw markup, i.e. ^GFA, char(27), etc
// *Note 2: Image width and image height must be divisible by 8
// *Note 3: Newline/Carriage Return must be appended manually
// *Note 4: Images should be strictly black and white
// Zebra (EPL):
qz.appendImage("image.png", "EPL");
while (!qz.isDoneAppending()) {} // wait
qz.append("\r\n");
// Zebra (ZPLII):
qz.appendImage("image.png", "ZPLII");
while (!qz.isDoneAppending()) {} // wait
qz.append("\r\n");
// Zebra (CPCL):
qz.appendImage("image.png", "CPCL");
while (!qz.isDoneAppending()) {} // wait
qz.append("\r\n");
// Epson (ESCP):
qz.appendImage("image.png", "ESCP");
while (!qz.isDoneAppending()) {} // wait
qz.append("\r\n");
// Base64
qz.appendImage("data:image/png;base64,AAAAAAAAA...", "ZPLII");
qz.append("\n");
// DeskJet/LaserJet, etc (don't mix with raw devices)
// Paper size/orientation since version 1.4.5
qz.setPaperSize("210mm", "297mm"); // A4
// qz.setPaperSize("8.5in", "11.0in"); // US Letter
qz.setAutoSize(true); // Preserve proportions
qz.setOrientation("landscape"); // Default is "portrait"
qz.appendImage("image.png"); // Append our image. Note: Wait for this to finish, or implement "jzebraDoneAppending()"
qz.print();
HTML Printing
- Since version 1.4.5, qz-print can print advanced HTML components by rendering an HTML component to an image using the html2canvas jQuery plugin (bundled in the /dist/js folder).
// HTML
<body id="content" bgcolor="#FFF380"> ...
<canvas id="hidden_screenshot" style="display:none;" /> ...
// JavaScript (jQuery)
$("#content").html2canvas({
canvas: hidden_screenshot,
onrendered: function() {
qz.append64($("canvas")[0].toDataURL('image/png'));
qz.printPS();
}
});
Note: HTML id#content
can be virtually any HTML component. HTML idhidden_screenshot
is a temporary place to draw the content and should be setdisplay=none
to prevent the render from becoming visiable.
- Since version 1.3.2, qz-print has the ability to print basic HTML components to a PostScript style printer directly from the browser. (PostScript printers include all major LaserJet, DeskJet, PSC, Home Printers, etc). Mileage may vary across different operating systems. Please file a bug report using ISSUES link above if you encounter issues.
// Basic HTML Printing
qz.appendHTML("<html><h1><font color=Red>Hello world!</font></h1>qz-print HTML Printing Demo</html>");
qz.printHTML();
// Printing using extra spaces, fixed font, dashes
var text = "*no-line-break* Hello from ’qz-print’ *no-line-break*";
// Fix whitespace and special character behavior
text = text.replace(/ /g, " ").replace(/’/g, "'").replace(/-/g,"‑");
qz.appendHTML('<html><table border=1 style="font-size:10pt; font-face:\'Courier New\';"><tr><td>' + text + '</td></tr></table></html>');
qz.printHTML();
// Printing an existing HTML file
qz.appendHTMLFile("../form.html");
// Wait for append to finish
while (!qz.isDoneAppending()) { // wait }
qz.printHTML();
Linux HTML Printing: Please note, there is a bug preventing margins from working properly on Linux: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6726691
Experimental / Work Arounds
- Since version 1.4.6, An OSX-only work-around was added to qz-print that allows printing through CUPS command line (
lp -o raw
), Issue 87.
// Alternate OSX raw printing via CUPS
qz.useAlternatePrinting(true);
Serial Communication
- Since version 1.6.0, You can send and receive data using the jSSC plugin (requires /dist/lib/jssc_qz.jar).
// List serial ports
qz.findPorts();
function jzebraDoneFindingPorts() {
var ports = qz.getPorts().split(",");
for (p in ports) {
alert(ports[p]);
}
}
// Open a serial port
qz.openPort("COM1"); //Can be dev/ttyS0, /dev/ttyUSB0, depending on platform
function jzebraDoneOpeningPort(portName) {
alert("Port [" + portName + "] is open!");
}
// Send serial data
// Beggining and ending patterns that signify port has responded
// chr(2) and chr(13) surround data on a Mettler Toledo Scale
qz.setSerialBegin(chr(2));
qz.setSerialEnd(chr(13));
// Baud rate, data bits, stop bits, parity, flow control
// "9600", "7", "1", "even", "none" = Default for Mettler Toledo Scale
qz.setSerialProperties("9600", "7", "1", "even", "none");
// Send raw commands to the specified port.
// W = weight on Mettler Toledo Scale
qz.send(document.getElementById("port_name").value, "\nW\n");
// Retrieve serial response (automatically called)
function jzebraSerialReturned(portName, data) {
alert("Port [" + portName + "] returned data:\n\t" + data);
}
// Close a serial port
qz.closePort("COM1"); //Can be dev/ttyS0, /dev/ttyUSB0, depending on platform
function jzebraDoneClosingPort(portName) {
alert("Port [" + portName + "] is open!");
}
End of Tutorial
Conclusion
This tutorial needs work. Please help by submitting changes. Email questions or suggestions to the author.
Alternatively, For questions, feedback and updates, subscribe to the qz-print Mailing List on Google Groups:
http://groups.google.com/group/jzebra-users'>http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif' />