Printing from Websites part 2
Good Afternoon Developers! Today I’m continuing my discussion of printing from webpages. For my first post, see here.
Thankfully with http you can print from a mobile device, smartphone, tablet, or PC. No drivers are necessary, so Android devices without drivers can use this to print. No one has to install or run any software besides a browser. All this makes it very flexible to the devices your web app can be run on.
There are several limitations for this mode of printing. One is that you as a developer have to create the label yourself. Zebra printers primarily use a print language called ZPL. Normally the driver handles the conversion from document to print language. Another is some of the browser security settings block communicating to the printer. The third limitation is that there is no bi-directional capability. There is no way to verify if a printer is online or is capable of printing before or after sending a print job. Use this feature only in situations where it is not critical that the print job gets done, or you can easily reprint if the printer was off or out of paper. Another limitation with http printing is that the printer must be networked on the same network as the user. USB and Bluetooth connectivity are not options with this technology.
The easiest way to handle creating a print job is to install the Zebra Driver and set it up for how you want the labels to be printed. Then take a label design tool like Zebra Designer to create a reusable document format. If you are printing in a specific application, say shelf labels, most of the time you want the price always in one area of the label, and the UPC in another area. You can use Zebra Designer to lay this template out. When you want to print, you just send the basic information of the UPC and price for each label. This speeds up time to print and ensures the best quality images. You can also manipulate the ZPL directly as a simple text file. The Programming Guide has examples of how to do this. It also explains how to set up printers for Wi-Fi, as well as document formatting.
- Name badge demo: Shows how to take basic user input and embed it directly in a raw ZPL print string and print it.
- Type your own ZPL Script: Essentially the same as the other basic html page, take what’s in the textbox and send it as raw data to the printer.
- Print Configuration Label: Simple string to print status and setup information about the printer
- Print Labels from your Computer: Does the same thing as demo #4, but gets the templates from the local user’s PC instead of the server.
For the demos that print formats, there are two different types of formats, standard ZPL, and XML. XML printing is useful if data is already formatted in XML, say from a database.
The files that are in this Zip file are:
- ZCloudDemo.css: A standard css to make the webpage look nice and Zebra-ish.
- Cloud_Connect.png, Zebra_Tag_Horizontal.png, and icon.ico: images to make the page look nice and Zebra-ish.
- File_catalog.xml: used by the “Print Zebra Demo labels” functionality to provide a list of zpl files for users to choose from (without a PHP or ASP backend)
- Test.txt, test2.txt, and herbert2.txt: basic ZPL print format files used by the “Print Zebra Demo labels” demo.
To try it yourself, simply extract the zip folder anywhere on your computer and double click the HTTPPost_printing.html file. This will open your favorite internet browser. You will need to input the IP address of your Zebra printer, then you should be ready to print. If you are using Chrome or IE10+, the “Print Zebra Demo labels” demo won’t work unless you are running it from IIS.
Edit: If you are having a problem with print-jobs not going through, check the console log. If you see an error along the lines of "Access-Control-Allow-Origin header not found", please see my post .
Other Articles on this topic:
ISV Engineer - Zebra Technologies
Thanks for the valuable info - we're really excited about finally being able to print from cloud apps to zebra printers. We were able to print directly from the browser to a printer on the same network, and we're now trying to print from an app hosted on a different network. We're a little stuck and hoping you might be able to give us some direction.
In the ISV newsletter and the Link-OS programming guide, it mentions using weblink to connect to the "zebra servlet". Is there an existing servlet that the printer is supposed to connect to? Or do we have to build our own servlet first? And in that case, would we be able to get access to the Zebra servlet source code example or documentation on how to build it?
Really appreciate any help you could provide.
From the newsletter - <em>"During this process, the printer will request the servlet’s certificate to verify it’s a Zebra Servlet, while the servlet requests the printer’s certificate for verification. After both are certificates are authenticated, the printer sends the servlet its discovery packet."</em>
As a clarification, The weblink servlet is just creating a secure websocket connection and keeping track of the printers connected. If you want to create a websocket server yourself, you should be able to. The server security cert needs to be signed by us, but the directions on how to do that are in the documentation with the SDK.
The Zebra Weblink Servlet is already written and is downloadable as part of the <a href="https://www.zebra.com/us/en/products/software/barcode-printers/link-os/… Link-OS SDK</a>. When you download the SDK, there are actually SDK's for PC, Android, iOS, etc. The servlet is in the PC section Edit:the section is named Webservices and the servlet is specifically in the lib folder and named "zebra.war". There is documentation and a sample app included. We also have it running as a demo <a href="http://weblink.cloudapp.net/">here</a>. The servlet is very basic and just provides access to printers connected to it with the expectation that the SDK will be used to provide functionality for your website.
Hope this helps and let us know if you have more questions,
The GK420d does support HTTP printing. To determine if it is currently enabled (or available) send the following string over an open communication channel (TCP or Serial) to the printer:
! U1 getvar "ip.http.enable"
Followed by a carriage return (hit Enter). The printer will respond with "on" or "off". Make sure your quotes are straight rather than slanted. if it responds with a "?" or there is no response, it's probably not an option. If it's off and you want to turn it on, send:
! U1 setvar "ip.http.enable" "on"
followed by a carriage return again. These commands can be found in the <a href="https://www.zebra.com/content/dam/zebra/manuals/en-us/software/zpl-zbi2… manual </a>page 1023.
EDIT: I forgot, you can also check if HTTP post is running by going to the printer webpage. Just open your favorite web browser and type the printer's IP address followed by /index.html like this: <a href="http://10.80.127.111/index.html">http://10.80.127.111/index.html</a>
The printer has a mini webserver that you can use do set up, see previews of labels, get a directory listing, check real-time status, etc. This is all working off the HTTP system that it uses to handle POST messages for printing.
In the post you said "most Zebra printers are set up to accept this type of communication by default". Does the GK420D with ethernet support printing over http? Is there a way to tell which printers support this method of printing?
This article has been useful in giving us the hopes that we can achieve our usecase of being able to print from our web based application to a label printer in a diagnostic laboratory. However after spending a couple of days i have not yet been successful. The way you explained it sounded very simple and promising.Right now i am trying on zebra GC420t as the vendor we talked to suggested that's the cheapest model available and would serve our usecase. However this model does not come with a ethernet port.1. What are the options i have to achieve what i want?
2. I tried attaching a print server hardware to the above mentioned address hoping to get the IP address. To save some cost and for testing purposes I have bought a Digisol USB print server hardware. When i try to print from the html part of the demo you have attached by specifying the IP of the print server, it gives a 404 as the pstprint is not found. My guess is that the print server is not forwarding the http request to the printer. So will this not work? How do i provide this model an IP address. Do i need a zebra print server only? I read something about USB masking to IP address in a comment in this post. Will that help and how does that work? Is there any resource that might help me in understanding and implementing that?
3. The usecase we have is of printing labels for laboratory on a size 10mm * 25mm. There would be approximate 500-700 labels printed per day. And as mentioned we need to print it from our application which is served within a browser. Which model would you recommend? This is to help a NGO hospital so we would like to reduce cost as much as possible.
Have you tried to view the printer webpage? That should give you an idea if the print server is behaving correctly. I believe you are probably right in that it's not forwarding the http request to the printer. I don't have knowledge of that print server so I can't give much insight.
I don't necessarily agree that the GC will fit your use case based on what you've stated here. You will probably spend more on print server hardware (and print head replacements) than if you went with a slightly higher model. The TLP2824 Plus with Ethernet is only slightly more expensive than the GC and it's space saving as well.
Also, just to clarify, you are using labels that are longer than wide as they feed out of the printer? I ask because there is a minimum label length to these desktop printers. I'm looking it up now, but I believe it's 16mm, maybe more with the ribbon models. I'll add the length when I find it.
However, what we've realised now is that your code is not working with Safari on OS X and with Safari on iOS.
I think the reason for this is Access-Control-Allow-Origin.
Except Safari all browsers send the ZPL code to the printer although it is throwing an error / warning concerning Access-Control-Allow-Origin on ALL browsers!
As far as I know, async ajax requests rely on Access-Control-Allow-Origin. The problem is the webserver of the printer. It should return a correct 'Access-Control-Allow-Origin' header!
So my question is:
<strong>How can we tell the webserver of the printers to respond with a correct 'Access-Control-Allow-Origin' header? E.g. "<code>Access-Control-Allow-Origin: *" </code>or with an IP range or with a domain name!</strong>
I hope, you have an idea. Thanks!
this is the error message in Google Chrome:
<strong>XMLHttpRequest cannot load <a href="http://10.88.21.121/pstprnt">http://10.88.21.121/pstprnt</a>. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '<a href="http://10.88.21.10">http://10.88.21.10</a>' is therefore not allowed access.</strong>
thanks for your replay. The error actually is displayed on all browsers! The difference is that except of Safari, all browsers still send the zpl code and the label is printed. So you will not notice at first glance.
I only noticed this error because it did not work on my iPhone. I then started searching and then I also noticed that it is not working on Safari on OS X and that the errors are displayed on all browsers. To my mind the reason for the error is that the webserver of the printer does not send a <strong>Access-Control-Allow-Origin </strong>header at all.
We use this printing feature on two different apps which run in a normal browser. One app is totally local, which means it is within the intranet (server, clients and printers) and we are working with static IPs. The second app is run in the cloud with the tablets and the printers being in the same local network and subnet.
We also tried to work with local domain-names e.g. server.example.local, tablet1.example.local and printer1.example.local for the local app, but this does not help either.
So as stated several times, a correct Access-Control-Allow-Origin header would solve it.
One workaround is sending the httprequest to a local server which responds with a correct header and forwards the request to the printer by using telnet.
The code would look like this:
<em> /* Set country settings */</em>
<em> header("Access-Control-Allow-Origin: *");</em>
<em> header("Content-Type: text/html; charset=utf-8");</em>
<em> setlocale (LC_ALL, "de_DE");</em>
<em> /* Receive data for printing */</em>
<em> $PrinterIP = $_POST["PrinterIP"];</em>
<em> $PrintData = $_POST["ZplCode"];</em>
<em> /* Open a telnet connection to the printer, then push all the data into it. */</em>
<em> echo 'Successfully Printed';</em>
<em> catch (Exception $e) </em>
<em> echo 'Caught exception: ', $e->getMessage(), "\n";</em>
The problem is, we are loosing speed by using this detour...
I did not read your last comment thoroughly at first. Sorry about that.
Can you post the IP adresses of your setup so can have an idea how they connect together. On my local setup the server runs on 10.88.21.10, the printer on 10.88.21.121 and the tablet on 10.88.21.101. So they are all within the same network. The webserver is IIS7.5 with PHP 5.3.
The clients OS is either Windows Server 2008 R2 as terminal server or Mac OS X 10.10.4 both with the latest browsers (Chrome 44.0.2403.130 (64-bit), FirefoxESR 38.1.1 and Safari 8.0.7) versions.
Hope this helps.
I understand your frustration. I agree that the printer needs to send a specific CORS or Access-Control-Allow-Origin header for Safari to let it through. I'm trying to put together a setup to test if the printer is capable of providing this. Unfortunately it's taking some time as I research options and fight the corporate network here. I initially tested PC Chrome, IE10, and Firefox using a similar setup to what you have (server on 10.80.127.137, PC on 10.80.127.43, and printer on 10.80.127.96). I'm sorry to say I never noticed the Access-Control-Allow-Origin header error on those browsers, although going back and looking, it is definitely there. During my initial testing I was not able to get a MAC on the same network, so I put the html file on the MAC and tested Safari that way. Of course it went through, as the request was not cross-origin at that point.
Now I'm going through several ideas on how to get the printers' print server to send the correct response. I should know in the next couple of days. The reality is it may not be able to right now. The web-servers on our printers are older and not updated much. Based on my testing, if it turns out that it isn't capable, I will submit a bug. It may take some time to for a fix to be released. Another option I'm looking into, if it turns out the printer is incapable, is creating a browser extension. The security on these plug-ins is much less and it looks like most of them allow this type of communication through.
In the end, you are the third person in the last week to have found this issue, so it has my highest priority to figure out how to handle it. I will respond when I know a little more. Thanks for your patience.
Hi Jan and anyone else having this issue,
I posted my response as a separate post here: <a href=""></a>
We don't really have a prepackaged solution for this. Due to browser security, I doubt this will be an option any time soon. As far as I know, the only way to print over Bluetooth from an iOS browser is to have a printing app also installed on the device. One of our partners, <a href="http://www.arrowheadphx.com/mobi-print/">Arrowhead</a>, has a very nice one that will take print data or images from a browser on iOS. Another option is you can write your own app in X-Code. I suggest using our <a href="https://www.zebra.com/us/en/products/software/barcode-printers/link-os/… SDK</a> and registering a <a href="https://developer.apple.com/library/ios/documentation/iPhone/Conceptual… Schema</a> to send the print data to the app.
Hope this helps, Robin
do you have any solution to make this happen?
I run with your demo codes with half success. I think it is great to get one working. We want both printers to print through web pages.
I have two kinds of zebra label printers, one is ZDesigner 110XiIII Plus 600DPI and the other model is ZDesigner ZM400 300 dpi (ZPL). The latter one could print label through the <a href="http://ipAddre/pstprnt">http://ipAddre/pstprnt</a> but the former (110XiIII) did not since printer-ip-address/pstprnt or printer-ip-address/printer/pstprnt responded with
<h3>404 Not Found.</h3>
Do you think my 110XiIII printer need upgrade to have the pstprnt program or somehow I could find pstprnt from the printer web server? The chrome console message like:
XMLHttpRequest cannot load <a href="http://ipaddress/pstprnt">http://ipaddress/pstprnt</a>. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '<a href="http://mywebportal">http://mywebportal</a>' is therefore not allowed access. The response had HTTP status code 404.
Note: the one which did not work has the printer web page like: <a href="http://ipaddress/printer/index.html">http://ipaddress/printer/index.htm…; instead of <a href="http://ipaddress/index.html">http://ipaddress/index.html</a>.
Thank you very much for your instruction, but what I see from their document is just an URL, I have no idea how to use it, is there any sample code which implement this feature or more details example?
To clarify how this works, you are calling on the browser to open a webpage, but rather than the standard <a href="http://">http://</a>, you use the custom URL Arrowhead:// Arrowhead has registered that url scheme (in your phone when it was installed) as it's own. The browser then knows to open the Arrowhead app, just like if you have facebook or many other apps installed and you link to them. You are also adding in your link what you want to print and that you would like the Arrowhead app to reopen your webpage when it's done. That's what the callback url is for.
Does this make sense?
You are absolutely right, the principle should be like that, but if there is sample code that would be better, so that I know how to process error, and I don't have to spend time to try if it works. thank you very much, I will contact Arrowhead to see if they have some sample code.
Can I print images from Website? If possible could you please provide some snippet?
As I begin my investigations into a Zebra printer, I want to be sure I'm selecting a model that supports this functionality. Is there an easy way to identify the printers you sell that support printing via HTTP Post? I can't seem to find this information on your site.
I basically want to check wether
I have the same issue with Matt, I am working on a small project that requires http post print. Could you or any one can recommend an inexpensive receipt printer? cheaper is better, just need basic receipt printer that support http post print, Thanks!!!
This post was from a while ago...curious if you received the information you were requesting. I am interested in HTTP Post printing but have no idea which Zebra printers support this functionality. Any help would be much appreciated!
My zebra label printers is ZDesigner ZM400 300 dpi (ZPL).
I want to send the zpl to printer from the browser. Printer's ip is 10.64.57.105(the same network with my PC). But the <a href="http://10.64.57.105/pstprnt">http://10.64.57.105/pstprnt</a> responded with
<strong>404 NOT FOUND</strong>
Can you tell me whether the solution is available now? or what the printer need upgrade to have the pstprnt program or somehow I could find pstprnt from the printer web server?
I am using a QLn420 Bluetooth printer. and trying to print a zpl file from a chrome page on an android device.
we are trying to do it using "Zebra Print Connect" app using android intents,
we where able to call search Printer via NFC
using link below, and it works
Launch Zebra Intent
but we are unable to send a zpl file to the printer the same way.
how can that be done ?
Hope this thread is still monitored.
I've encountered a problem with extended characters that I can't seem to get to the bottom of.
If I send a document containing this ZPL line directly to our GX430t (lpr -o raw) it prints correctly:
(That's hex 81 for ü and hex 94 for ö from code page 850; my terminal expects UTF-8 so the characters don't display as printed)
But if I send the same document to the same printer via XMLHttpRequest, an extra character is printed in front of the ü and the ö. It appears to be the graphic character ┬ with 850 hex c2.
Does this make any sense?
thank you for your useful examples. I'm trying to print using an http post like in your example, on a printer model ZTC TLP2844-Z-200dpi, but the address set in your html page HTTPPost_printing.html doesn't work. The printer web server response is about an error 404 for the url <a href="http://">http://</a>/pstprnt. I was wondering if you could know the page to send own ZPL script to ZTC TLP2844-Z printer.
Anyone having issues with CORS or wanting to POST print via HTTPS, please contact <a href="https://www.zebra.com/us/en/about-zebra/contact-zebra/contact-tech-supp… Technical Support</a>. It is the best method to get these concerns escalated.
Robin, can you please help with another issue about Zebra and EPL? It's about printing special characters via HTTP POST.We could chat by email, if it pleases you.
Excellent article! your example works fine for me, but when I try to implement it in my web page, it doesn't work because my web page is https and I get the message "Mixed Content: The page at '<a href="https://localhost:44310/Home/ProductSearch?pageNumber=1&pageSize=20…; was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint '<a href="http://192.168.0.75/pstprnt">http://192.168.0.75/pstprnt</a>'. This request has been blocked; the content must be served over HTTPS."
How can I have the printer working over a https service instead of http?
Thanks for suggesting the ~JD diagnostic. It allows me to see that there is indeed an extraneous hex c2 sent to the printer just before the non-ASCII character. And since I can see what is fed into XMLHttpRequest, I can be sure that XMLHttpRequest is adding the byte.
Since we don't generate the ZPL, I'm not sure what to do next but I understand the problem better.
Robin, can I use HTTP POST in a zebra installed in a network PC?
I use this adress: XX.X.X.XX/zebra (shared printer), or just works in a zebra's IP?
I try to add this path in your examples, but doesn´t works.
There is another method?
Thanks for this Robin very useful.
Looking to build a prototype for a manufacturing facility who will need to print QR codes, my aim is to use nodejs to output the codes directly to the printer.
For testing purposes could you recommend the cheapest Zebra printer which will fulfill the requirements (QR code and a LAN connection)? Hopefully I can pick one up secondhand. Do you think I might be able to use a USB version if I get windows to share the printer (will it give it a pseudo IP address I wonder?)
Huh... very cool!
How big a label do you need and how many do you think will print a day? If you only need a label that is a max 2" wide and only need to print occasionally, the 2824plus is a good option. If you need labels a little larger, the GC420 is the entry level, but it might be easier to get a used GK420. The GC does not offer Ethernet even as an option. Once you are in production and need high throughput, then you are looking at the Tabletop line of products. Entry level there is the ZT210. The nice thing is your raw ZPL for creating the QR code will work the same across all these products.
You can also set up your driver to take and send raw data, but this will still be slower. Another option is to create a small app to run on the PC (Java applet, or something similar) that will take the raw data and send it directly to the printer.
Hope this helps,
this is the error code in Safari for OS X:
<strong>"Error" Failed to load resource: the server responded with a status of 501 (Not Implemented) (pstprnt, line 0)</strong>
<strong>"Error" Failed to load resource: Origin <a href="http://10.88.21.10">http://10.88.21.10</a> is not allowed by Access-Control-Allow-Origin. (pstprnt, line 0)</strong>
<strong>"Error" XMLHttpRequest cannot load <a href="http://10.88.21.121/pstprnt">http://10.88.21.121/pstprnt</a>. Origin <a href="http://10.88.21.10">http://10.88.21.10</a> is not allowed by Access-Control-Allow-Origin. (printlabel.php, line 0)</strong>
Sorry about the several comments, but I could not include all the error messages in my first post.
I don't have any sample code, but you could contact Arrowhead.
I would try something like just using window.open() or window.location.assign().
For the iPhone (at least), you need to specify the Content-Type header as "text/plain".
Without that you get a blank post request.
I want to print to convert dynamic images into ZPL, If there any way to convert Images into ZPL code for .net application
is it possible to send a command to an ip adress to check if a zebra printer is connected to this IP?
Hi Mark, HTML generally uses UTF-8 encoding as well, so if you don't make sure the request is being sent with the same code page the printer is expecting(CP850), then you run into these types of issues. At least I think that's what is wrong. Either switch the printer to UTF-8 (^CI28) or make sure the terminal is sending CP850.
You can put the printer into dump mode to verify what the terminal is sending to the printer. Add ~JD to the beginning of your format and send the whole thing the way you have been. The printer will print the hex for each byte it receives and the ASCII representation if any. That way you can verify the bytes are correct CP850. Turn off and on the printer to reset it to normal mode.
Hi Russel, Please verify you can get to the printer webpage at all. Enter <a href="http://10.64.57.105/index.html">http://10.64.57.105/index.html</a> in your usual browser. If you see the page then the /pstprnt header might not be correct.
If the page does not show up, then it has been disabled. Use Setup utility to turn on HTTP - send
! U1 setvar "ip.http.enable" "on"
followed by a carriage return.
Your post on printing via HTTP was very helpful. I know the question below might be redundant to your explanation above with regards to getting feedback.
But I want to make sure if all doors closed in HTTP approach to get an appropriate response from the printer.
We are using Zebra ZT410 RFID printer and are communicating to the printer via HTTP post. By default printer sends a 200 "Successful" response as long as the communication is successful.
We would like to receive actual error feedback in case of any error while printing due to any hardware / ribbon / tag related issues.
Please suggest how this is possible via HTTP.
If the response as requested above is not possible,it is also OK if there is a way to receive the value of "odometer.rfid.valid._resettable" via:
1.) HTTP communication
2.) through some integrated communication via SAP system (which is our backend ERP system) in same network.
We cannot use any desktop applications or extensions for our requirement.
Any help here is very much appreciated !!
P.S.: I have reached out to Zebra technical support but I was asked to reach out to developer community for such requests.
Hello Raja Boyapati :
I would like to know if you were able to solve your problem? I am currently in a similar development and it would be ideal to get the EPC data that has been read or written at the time of printing the label. And get some kind of error status in case the label is not printed. Your experience or guidance would help me a lot. Thank you so much
The zip file is not longer accessible.
Can I still get it somewhere?