Print preview ZPL II commands using .NET WinForm before sending it to Zebra printer

35,570

Solution 1

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.

Solution 2

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.)

Solution 3

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.

Solution 4

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"

Solution 5

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);
}
Share:
35,570
hasan lamaa
Author by

hasan lamaa

Updated on August 11, 2021

Comments

  • hasan lamaa
    hasan lamaa almost 3 years

    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?

  • banno
    banno almost 13 years
    There are a few other ways to do this using the printer format the label without printing. Is having a printer in-line acceptable?
  • SleepNot
    SleepNot over 11 years
    What if I only have the printer driver installed and not the actual printer? Can I still be able to access this directory listing?
  • Ali Mst
    Ali Mst over 10 years
    For others looking for how to do this, see my answer that has the code to get the label preview.
  • bluish
    bluish over 10 years
    Seems good work! Could you add which printer vendor and model your code works with, please?
  • Ali Mst
    Ali Mst over 10 years
    @bluish - Zebra Label Printers. I tested it on a ZM400.
  • nbering
    nbering almost 10 years
    Also works with Zebra170Xi4. I've found that the image the printer generates creates a large amount of white space around the rendered label. I'm not sure if setting a label width in the ZPL will fix that (most of our designs do not).
  • JWiley
    JWiley almost 10 years
    What did you use for your printer IP address? Was it hooked up to your computer via USB? Or was it just under a print server? Any idea how I would use this just through USB or local network?
  • Ali Mst
    Ali Mst almost 10 years
    @JWiley - I don't know that this could work via USB. We use a printer that is on our LAN. It has a fixed IP address (setup by my system admins). You can get the IP address from the ZM400 printer that I used.
  • JWiley
    JWiley almost 10 years
    Your ZM400 has a fixed IP Address? It's not through LPT1? Any idea how I could use this method if I can assign an IP to the printer based on what computer it's connected to?
  • Ali Mst
    Ali Mst almost 10 years
    @JWiley - It will only work if your printer has an IP address that the caller can reach. I am not a "network guy" so I don't know if that is something that can be done they way you are saying. The easy way to check is to browse to the IP address. It should have a page to admin the printer.
  • JWiley
    JWiley over 9 years
    @Vaccano Any idea how I can send zpl that contains header info such as [CARD] SlotID=1 OrgName=C:\\mypath\\myfile.mmf CardSize=4096000 Description=mymmf ?