20
votes

I have an .NET Windows application that prints commands to Zebra printer using ZPL II or EPL2. Is there any way to print preview the data in a form before printing it directly from Zebra printer?

5

5 Answers

23
votes

Have a look at the Labelary web service, which allows you to convert ZPL to an image programmatically.

Just build a URL containing the ZPL that you want to render, get the image back from the web server, and show the image to the user from within your application.

string zpl = "YOUR ZPL HERE";
string url = "http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/" + zpl;
using (WebClient client = new WebClient()) {
    client.DownloadFile(url, "zpl.png");
}

There's also a ZPL viewer lets you edit and view ZPL directly on a web page.

12
votes

I needed the ability to show the label in my Application. So I hooked up Fiddler and figured out what the communication was to get the image of the label.

I got it running in LinqPad. The HTTP stuff can be cleaned up a bit, but I thought I would post the code for others to use:

void Main()
{
    string printerIpAddress = "10.92.0.167";
    string zpl="^XA^CFD^CVY^PON^FWN^LS0^LT0^LH15,17^FS^FO0,2^FO14,3^FH^FDHi^FS^XZ";

    // post the data to the printer
    var imageName = PostZplAndReturnImageName(zpl, printerIpAddress);

    // Get the image from the printer
    var image = LoadImageFromPrinter(imageName, printerIpAddress);

    Console.WriteLine(image);   
}


public static string PostZplAndReturnImageName(string zpl, string printerIpAddress)
{
    string response = null;
    // Setup the post parameters.
    string parameters = "data="+ zpl;
    parameters = parameters + "&" + "dev=R";
    parameters = parameters + "&" + "oname=UNKNOWN";
    parameters = parameters + "&" + "otype=ZPL";
    parameters = parameters + "&" + "prev=Preview Label";
    parameters = parameters + "&" + "pw=";

    // Post to the printer
    response = HttpPost("http://"+ printerIpAddress +"/zpl", parameters);

    // Parse the response to get the image name.  This image name is stored for one retrieval only.
    HtmlAgilityPack.HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(response);
    var imageNameXPath = "/html[1]/body[1]/div[1]/img[1]/@alt[1]";
    var imageAttributeValue = doc.DocumentNode.SelectSingleNode(imageNameXPath).GetAttributeValue("alt","");
    // Take off the R: from the front and the .PNG from the back.
    var imageName = imageAttributeValue.Substring(2);
    imageName = imageName.Substring(0,imageName.Length - 4);

    // Return the image name.
    return imageName;
}


public static string HttpPost(string URI, string Parameters) 
{
   System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
   req.Proxy = new System.Net.WebProxy();

   //Add these, as we're doing a POST
   req.ContentType = "application/x-www-form-urlencoded";
   req.Method = "POST";

   //We need to count how many bytes we're sending. 
   //Post'ed Faked Forms should be name=value&
   byte [] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters);
   req.ContentLength = bytes.Length;

   System.IO.Stream os = req.GetRequestStream();
   os.Write (bytes, 0, bytes.Length); //Push it out there
   os.Close ();

   System.Net.WebResponse resp = req.GetResponse();

   if (resp== null) return null;
   System.IO.StreamReader sr = 
         new System.IO.StreamReader(resp.GetResponseStream());
   return sr.ReadToEnd().Trim();
}

public static Image LoadImageFromPrinter(string imageName, string printerIpAddress)
{
    string url = "http://"+ printerIpAddress +"/png?prev=Y&dev=R&oname="+ imageName +"&otype=PNG";  

    var response = Http.Get(url);   

    using (var ms = new MemoryStream(response))
    {       
        Image image = Image.FromStream(ms);

        return image;
    }  


}

public static class Http
{
    public static byte[] Get(string uri)
    {               
        byte[] response = null;
        using (WebClient client = new WebClient())
        {
            response = client.DownloadData(uri);
        }
        return response;
    }   
}

This has the following References:

HtmlAgilityPack
System.Drawing
System.Net

and the following Uses:

HtmlAgilityPack
System.Drawing
System.Drawing.Imaging
System.Net

NOTE: I could not find a way to communicate with a serial/non-IP Addressed printer. (Though that does not mean that there is not a way.)

4
votes

If you're ok with using a Chrome Plugin, please try Simon Binkert's Zpl Printer. This plugin is based on the Labelary Web Service linked in previous comments.

See also: https://stackoverflow.com/a/33066790/3196753

Note, although this plugin runs inside Google Chrome, it can work with any application on the computer capable of sending raw commands.

chrome zpl printer

It can be configured to listen on localhost or dedicated IP address, so it can be used to emulate a ZPL printer on the PC and local network. If you need a local printer or printer share, you can set up a raw printer queue on the PC which points to it on hostname/ip and port and other desktop applications will be able to send ZPL to it.

Note, if you need to make it available to other computers on the network, make sure to change 127.0.0.1 in the Printer Settings to a valid LAN IP address.

2
votes

The only way to preview the label is on the printer's web page.

If you go to the printer's directory listing http://<printer IP>/dir and click on the saved label (or create a new one) then you can click "Preview Label"

0
votes

If you don't want to send your data to a cloud service you can have a look at our project we have developed an open ZPL viewer that converts ZPL data into a graphic. The project is based on .NET.

More Informations are available here BinaryKits.Zpl.Viewer (GitHub)

Also a nuget package is available

PM> install-package BinaryKits.Zpl.Viewer

Example code

IPrinterStorage printerStorage = new PrinterStorage();
var drawer = new ZplElementDrawer(printerStorage);

var analyzer = new ZplAnalyzer(printerStorage);
var analyzeInfo = analyzer.Analyze("^XA^FT100,100^A0N,67,0^FDTestLabel^FS^XZ");

var labels = new List<LabelDto>();
foreach (var labelInfo in analyzeInfo.LabelInfos)
{
    var imageData = drawer.Draw(labelInfo.ZplElements);
}