从网页打印条形码到Zebra打印机

时间:2012-06-10 09:21:48

标签: printing web barcode

我们正在尝试将条形码从网页打印到我们的Zebra打印机。

我想知道是否有办法使用打印机自己的字体打印它们,也许使用网络字体或者我知道使用的字体名称?

我一直在尝试使用php条形码生成器,它基本上生成包含条形码的图像。事实上,我已经尝试了几天,但没有成功。

问题是当我打印它们时扫描仪无法读取。我试图将图像分辨率更改为与打印机的分辨率相匹配(203dpi),也尝试使用图像尺寸和格式进行播放,但打印后的条形码仍然无法扫描。

那么有人有这方面的经验吗?

打印机:Zebra TLP 2844

每页所需的条形码:

  • 01 Code39水平(仅在非常特定的尺寸和浏览器下打印时可扫描)
  • 01 Code128垂直(仍然无法使其工作,打印总是非常模糊,不会被扫描)

===========

我取得了一些进展,我发现这台打印机支持EPL2语言,所以我试图用它来打印出条形码。

首先我需要启用传递模式,我在打印机选项>上执行了此操作。高级设置>杂。

现在我可以使用打印机的内置字体无可挑剔地打印条形码:D使用此命令:

ZPL: B10,10,0,1,2,2,60,N, “TEXT-GOES-HERE” :ZPL

但是我只能用记事本打印它,我仍然无法从浏览器打印出来......这可能是LF被CR + LF取代的问题......

如何克服这个问题??

===========

我正在尝试打印的标签实际上在条形码之前有一些文字,一些html表格很好地格式化。所以我需要首先打印它,在中间我需要粘贴一个漂亮的标签,然后再添加一些文本。

所以我不能用纯EPL2打印整个东西,我想知道我是否可以使用html + EPL2 + html中的一些来实现我的目标或者是不允许的? = /

8 个答案:

答案 0 :(得分:20)

你遇到了一些障碍:

1)当您通过操作系统安装的打印机驱动程序进行打印时,打印机驱动程序正在尝试获取发送给它的数据,并(重新)光栅化或缩放它以用于输出设备(Zebra打印机)。由于打印机在203dpi时的分辨率相对较低,因此打印驱动程序不必花费太大的时间来缩放打印机,因为它会使条形码的质量失去一定的完整性。这就是使用直接ZPL命令生成的条形码 更可靠的原因。

2)由于Web浏览器通过不允许访问客户端计算机而有目的地提供安全性,因此您无法直接与客户端连接的打印机进行通信。此沙箱有助于保护用户免受恶意软件的侵害,因此恶意网站无法执行将文件写入客户端计算机或将输出直接发送到打印机等设备的操作。因此,您无法通过浏览器直接将ZPL命令发送到客户端连接的打印机。

然而,有一种方法可以做你所描述的。如果您对访问尝试打印到Zebra打印机的站点的客户端计算机有一定程度的控制,则所需的步骤通常才有用。例如,这只会由公司网络上的计算机使用,或者由愿意安装您需要编写的小型应用程序的客户使用。为此,您需要查看以下步骤:

A)您需要编写自己的自定义MIME类型。这基本上只是您想要使用的任何名称都不会与任何registered MIME types发生碰撞。

B)接下来,您将定义一个文件扩展名,该扩展名将映射到您的自定义MIME类型。为此,您通常需要配置Web服务器(此步骤取决于您使用的Web服务器),以允许您要定义的新MIME类型以及用于这些类型文件的文件扩展名。

C)然后在您的Web应用程序上,当您想要输出ZPL数据时,使用映射到新MIME类型的文件扩展名将其写入文件。然后,一旦生成文件,您可以提供HTML链接,或将客户端浏览器重定向到该文件。此时,您可以通过手动将直接创建的文件复制到原始打印机端口来测试文件是否正常工作。

D)接下来,您需要编写一个可以安装在客户端上的小应用程序。安装应用程序后,您需要将其自身注册为自定义MIME类型的有效消费应用程序。如果浏览器检测到已安装的应用程序用于指定MIME类型的文件,它只是将该文件写入客户端计算机上的临时目录,然后尝试使用临时文件启动相同的已注册MIME类型的应用程序。应用程序的参数。因此,您的应用程序现在只读取浏览器传递给它的文件,然后尝试将其直接转储到打印机。

这是为了完成您所描述的内容而概述您需要做什么。某些具体步骤取决于您使用的Web服务器类型以及客户端所使用的操作系统。但这是高级概述,可以让您完成您的尝试。

答案 1 :(得分:8)

如果您考虑加载一个Java小程序,qz-print(以前的jzebra)可以完全按照您的描述进行操作,并与评论中提到的LP2844很好地配合使用。

https://code.google.com/p/jzebra/

答案 2 :(得分:4)

我们为网络应用做了什么:

1)下载免费的printfile应用http://www.lerup.com/printfile/

" PrintFile是一个免费的MS Windows实用程序,可以让您快速轻松地打印文件。该程序可识别纯文本,PostScript,Encapsulated PostScript(EPS)和二进制格式。使用这个程序可以节省大量纸张,从而节省宝贵的自然资源。"

首次运行PrintFile时,请进入高级选项并启用"直接发送给打印机"。

2)在Windows中将ZEBRA打印机设置为通用文本打印机。

2)在Web应用程序中生成一个file.prt文件,该文件只是一个纯文本EPL文件。

3)双击下载的文件将立即打印条形码。奇迹般有效。您甚至可以设置PrintFile,以便您甚至不会看到gui。

答案 3 :(得分:3)

我正在开发类似的东西。 我需要从我的webapp打印到LP2844。问题是我的webapp位于云端的远程服务器(Amazon EC2)中,打印机将位于仓库中。

我的解决方案: webapp为包含条形码的标签生成EPL2 code,然后发布PubNub message。 我写了一个小的C#程序,它运行在连接打印机的计算机上。程序接收消息,然后将代码发送到打印机。

答案 4 :(得分:2)

您还可以在文本文件中发送ZPL命令(您可以在一个文件中打包多个标签)并让用户打开并通过Windows记事本打印文件。唯一需要注意的是,他们必须删除默认的页眉和页脚(文件 - >页面设置)。

它进行了一些用户培训,但如果您无法控制客户端计算机,则可以接受。

答案 5 :(得分:2)

我遵循了#34; Tres Finocchiaro"提出的想法。在我的申请基于:

  1. ASP.NET 4.0
  2. IIS
  3. Chrome,IExplorer,Firefox
  4. Zebra TLP 2844
  5. EPL protocolo
  6. 不幸的是,由于当前浏览器的安全性问题,jzebra需要进行一些改进以进行核心工作。

    安装jzebra

    Downlod jzebdra和dist目录我复制到你的目录(例如mydir):

      • MYDIR
        • JS
          • ..
          • deployJava.js
        • LIB
          • ..
        • QZ-print.jar
        • qz-print_jnlp.jnlp

    创建print.html

    <html>
    <script type="text/javascript" src="js/deployJava.js"></script>
    <script type="text/javascript">
        /**
        * Optionally used to deploy multiple versions of the applet for mixed
        * environments.  Oracle uses document.write(), which puts the applet at the
        * top of the page, bumping all HTML content down.
        */
        deployQZ();
    
        /** NEW FUNCTION **/
        function initPrinter() {
            findPrinters();
            useDefaultPrinter();
        }
    
        /** NEW FUNCTION **/    
        function myalert(txt) {
            alert(txt);
        }
    
    
        /**
        * Deploys different versions of the applet depending on Java version.
        * Useful for removing warning dialogs for Java 6.  This function is optional
        * however, if used, should replace the <applet> method.  Needed to address 
        * MANIFEST.MF TrustedLibrary=true discrepency between JRE6 and JRE7.
        */
        function deployQZ() {
            var attributes = {id: "qz", code:'qz.PrintApplet.class', 
                archive:'qz-print.jar', width:1, height:1};
            var parameters = {jnlp_href: 'qz-print_jnlp.jnlp', 
                cache_option:'plugin', disable_logging:'false', 
                initial_focus:'false'};
            if (deployJava.versionCheck("1.7+") == true) {}
            else if (deployJava.versionCheck("1.6+") == true) {
                delete parameters['jnlp_href'];
            }
            deployJava.runApplet(attributes, parameters, '1.5');
        }
    
        /**
        * Automatically gets called when applet has loaded.
        */
        function qzReady() {
            // Setup our global qz object
            window["qz"] = document.getElementById('qz');
            var title = document.getElementById("title");
            if (qz) {
                try {
                    title.innerHTML = title.innerHTML + " " + qz.getVersion();
                    document.getElementById("content").style.background = "#F0F0F0";
                } catch(err) { // LiveConnect error, display a detailed meesage
                    document.getElementById("content").style.background = "#F5A9A9";
                    alert("ERROR:  \nThe applet did not load correctly.  Communication to the " + 
                        "applet has failed, likely caused by Java Security Settings.  \n\n" + 
                        "CAUSE:  \nJava 7 update 25 and higher block LiveConnect calls " + 
                        "once Oracle has marked that version as outdated, which " + 
                        "is likely the cause.  \n\nSOLUTION:  \n  1. Update Java to the latest " + 
                        "Java version \n          (or)\n  2. Lower the security " + 
                        "settings from the Java Control Panel.");
              }
          }
        }
    
        /**
        * Returns whether or not the applet is not ready to print.
        * Displays an alert if not ready.
        */
        function notReady() {
            // If applet is not loaded, display an error
            if (!isLoaded()) {
                return true;
            }
            // If a printer hasn't been selected, display a message.
            else if (!qz.getPrinter()) {
               /** CALL TO NEW FUNCTION **/
                initPrinter();
                return false;
            }
            return false;
        }
    
        /**
        * Returns is the applet is not loaded properly
        */
        function isLoaded() {
            if (!qz) {
                alert('Error:\n\n\tPrint plugin is NOT loaded!');
                return false;
            } else {
                try {
                    if (!qz.isActive()) {
                        alert('Error:\n\n\tPrint plugin is loaded but NOT active!');
                        return false;
                    }
                } catch (err) {
                    alert('Error:\n\n\tPrint plugin is NOT loaded properly!');
                    return false;
                }
            }
            return true;
        }
    
        /**
        * Automatically gets called when "qz.print()" is finished.
        */
        function qzDonePrinting() {
            // Alert error, if any
            if (qz.getException()) {
                alert('Error printing:\n\n\t' + qz.getException().getLocalizedMessage());
                qz.clearException();
                return; 
            }
    
            // Alert success message
            alert('Successfully sent print data to "' + qz.getPrinter() + '" queue.');
        }
    
        /***************************************************************************
        * Prototype function for finding the "default printer" on the system
        * Usage:
        *    qz.findPrinter();
        *    window['qzDoneFinding'] = function() { alert(qz.getPrinter()); };
        ***************************************************************************/
        function useDefaultPrinter() {
            if (isLoaded()) {
                // Searches for default printer
                qz.findPrinter();
    
                // Automatically gets called when "qz.findPrinter()" is finished.
                window['qzDoneFinding'] = function() {
                    // Alert the printer name to user
                    var printer = qz.getPrinter();
                    myalert(printer !== null ? 'Default printer found: "' + printer + '"':
                        'Default printer ' + 'not found');
    
                    // Remove reference to this function
                    window['qzDoneFinding'] = null;
                };
            }
        }
    
        /***************************************************************************
        * Prototype function for finding the closest match to a printer name.
        * Usage:
        *    qz.findPrinter('zebra');
        *    window['qzDoneFinding'] = function() { alert(qz.getPrinter()); };
        ***************************************************************************/
        function findPrinter(name) {
            // Get printer name from input box
            var p = document.getElementById('printer');
            if (name) {
                p.value = name;
            }
    
            if (isLoaded()) {
                // Searches for locally installed printer with specified name
                qz.findPrinter(p.value);
    
                // Automatically gets called when "qz.findPrinter()" is finished.
                window['qzDoneFinding'] = function() {
                    var p = document.getElementById('printer');
                    var printer = qz.getPrinter();
    
                    // Alert the printer name to user
                    alert(printer !== null ? 'Printer found: "' + printer + 
                        '" after searching for "' + p.value + '"' : 'Printer "' + 
                        p.value + '" not found.');
    
                    // Remove reference to this function
                    window['qzDoneFinding'] = null;
                };
            }
        }
    
        /***************************************************************************
        * Prototype function for listing all printers attached to the system
        * Usage:
        *    qz.findPrinter('\\{dummy_text\\}');
        *    window['qzDoneFinding'] = function() { alert(qz.getPrinters()); };
        ***************************************************************************/
        function findPrinters() {
            if (isLoaded()) {
                // Searches for a locally installed printer with a bogus name
                qz.findPrinter('\\{bogus_printer\\}');
    
                // Automatically gets called when "qz.findPrinter()" is finished.
                window['qzDoneFinding'] = function() {
                    // Get the CSV listing of attached printers
                    var printers = qz.getPrinters().split(',');
                    for (i in printers) {
                        myalert(printers[i] ? printers[i] : 'Unknown');      
                    }
    
                    // Remove reference to this function
                    window['qzDoneFinding'] = null;
                };
            }
        }
    
        /***************************************************************************
        * Prototype function for printing raw EPL commands
        * Usage:
        *    qz.append('\nN\nA50,50,0,5,1,1,N,"Hello World!"\n');
        *    qz.print();
        ***************************************************************************/
        function print() {
            if (notReady()) { return; }
    
            // Send characters/raw commands to qz using "append"
            // This example is for EPL.  Please adapt to your printer language
            // Hint:  Carriage Return = \r, New Line = \n, Escape Double Quotes= \"
            qz.append('\nN\n');            
            qz.append('q609\n');
            qz.append('Q203,26\n');
            qz.append('B5,26,0,1A,3,7,152,B,"1234"\n');
            qz.append('A310,26,0,3,1,1,N,"SKU 00000 MFG 0000"\n');
            qz.append('A310,56,0,3,1,1,N,"QZ PRINT APPLET"\n');
            qz.append('A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"\n');
            qz.append('A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"\n');
            qz.append('A310,146,0,3,1,1,N,"QZINDUSTRIES.COM"');
    
            // Append the rest of our commands
            qz.append('\nP1,1\n');
    
            // Tell the applet to print.
            qz.print();
         }
    
        /***************************************************************************
        * Prototype function for logging a PostScript printer's capabilites to the
        * java console to expose potentially  new applet features/enhancements. 
        * Warning, this has been known to trigger some PC firewalls
        * when it scans ports for certain printer capabilities.
        * Usage: (identical to appendImage(), but uses html2canvas for png rendering)
        *    qz.setLogPostScriptFeatures(true);
        *    qz.appendHTML("<h1>Hello world!</h1>");
        *    qz.printPS();
        ***************************************************************************/ 
        function logFeatures() {
            if (isLoaded()) {
                var logging = qz.getLogPostScriptFeatures();
                qz.setLogPostScriptFeatures(!logging);
                alert('Logging of PostScript printer capabilities to console set to "' + !logging + '"');
            }
        }
    
        /***************************************************************************
        ****************************************************************************
        * *                          HELPER FUNCTIONS                             **
        ****************************************************************************
        ***************************************************************************/
    
        function getPath() {
            var path = window.location.href;
            return path.substring(0, path.lastIndexOf("/")) + "/";
        }
    
        /**
        * Fixes some html formatting for printing. Only use on text, not on tags!
        * Very important!
        *   1.  HTML ignores white spaces, this fixes that
        *   2.  The right quotation mark breaks PostScript print formatting
        *   3.  The hyphen/dash autoflows and breaks formatting  
        */
        function fixHTML(html) {
            return html.replace(/ /g, "&nbsp;").replace(/’/g, "'").replace(/-/g,"&#8209;"); 
        }
    
        /**
        * Equivelant of VisualBasic CHR() function
        */
        function chr(i) {
            return String.fromCharCode(i);
        }
    
        /***************************************************************************
        * Prototype function for allowing the applet to run multiple instances.
        * IE and Firefox may benefit from this setting if using heavy AJAX to
        * rewrite the page.  Use with care;
        * Usage:
        *    qz.allowMultipleInstances(true);
        ***************************************************************************/ 
        function allowMultiple() {
          if (isLoaded()) {
            var multiple = qz.getAllowMultipleInstances();
            qz.allowMultipleInstances(!multiple);
            alert('Allowing of multiple applet instances set to "' + !multiple + '"');
          }
        }
    </script>
    
        <input type="button" onClick="print()" />
        </body>
    </html>
    

    提供的代码基于&#34; jzebra_installation / dist / sample.html&#34;。

答案 6 :(得分:2)

我正在使用QZ Tray将网页上的标签打印到Zebra热敏打印机。

在QZ Tray的demo/js文件夹中,与QZ Tray应用程序通信需要三个JavaScript文件 - dependencies/rsvp-3.1.0.min.jsdependencies/sha-256.min.jsqz-tray.js

在项目中包含以下JavaScript文件:

<script type="text/javascript" src="/lib/qz-tray/rsvp-3.1.0.min.js"></script>
<script type="text/javascript" src="/lib/qz-tray/sha-256.min.js"></script>
<script type="text/javascript" src="/lib/qz-tray/qz-tray.js"></script>

将标签打印到Zebra热敏打印机的最简单方法如下所示。

<script type="text/javascript">
qz.websocket.connect().then(function() {
   // Pass the printer name into the next Promise
   return qz.printers.find("zebra");
}).then(function(printer) {
   // Create a default config for the found printer
   var config = qz.configs.create(printer);

   // Raw ZPL
   var data = ['^XA^FO50,50^ADN,36,20^FDRAW ZPL EXAMPLE^FS^XZ'];

   return qz.print(config, data);
}).catch(function(e) { console.error(e); });
</script>

有关详细信息,请参阅How to print labels from a web page to Zebra thermal printer

答案 7 :(得分:0)

尝试创建一个控制客户端打印的websocket,并将带有ajax的数据从页面发送到localhost。

/// websocket
using System;
using System.Net;
using System.Net.WebSockets;
using System.Text;
using System.Threading;

namespace Server
{
    class Program
    {
        public static WebsocketServer ws;
        static void Main(string[] args)
        {
            ws = new Server.WebsocketServer();
            ws.LogMessage += Ws_LogMessage;
            ws.Start("http://localhost:2645/service/");
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }

        private static void Ws_LogMessage(object sender, WebsocketServer.LogMessageEventArgs e)
        {
            Console.WriteLine(e.Message);
        }
    }

    public class WebsocketServer
    {
        public event OnLogMessage LogMessage;
        public delegate void OnLogMessage(Object sender, LogMessageEventArgs e);
        public class LogMessageEventArgs : EventArgs
        {
            public string Message { get; set; }
            public LogMessageEventArgs(string Message)
            {
                this.Message = Message;
            }
        }

        public bool started = false;
        public async void Start(string httpListenerPrefix)
        {
            HttpListener httpListener = new HttpListener();
            httpListener.Prefixes.Add(httpListenerPrefix);
            httpListener.Start();
            LogMessage(this, new LogMessageEventArgs("Listening..."));
            started = true;

            while (started)
            {
                HttpListenerContext httpListenerContext = await httpListener.GetContextAsync();
                if (httpListenerContext.Request.IsWebSocketRequest)
                {
                    ProcessRequest(httpListenerContext);
                }
                else
                {
                    httpListenerContext.Response.StatusCode = 400;
                    httpListenerContext.Response.Close();
                    LogMessage(this, new LogMessageEventArgs("Closed..."));
                }
            }
        }

        public void Stop()
        {
            started = false;
        }
        private async void ProcessRequest(HttpListenerContext httpListenerContext)
        {
            WebSocketContext webSocketContext = null;

            try
            {
                webSocketContext = await httpListenerContext.AcceptWebSocketAsync(subProtocol: null);
                LogMessage(this, new LogMessageEventArgs("Connected"));
            }
            catch (Exception e)
            {
                httpListenerContext.Response.StatusCode = 500;
                httpListenerContext.Response.Close();
                LogMessage(this, new LogMessageEventArgs(String.Format("Exception: {0}", e)));
                return;
            }

            WebSocket webSocket = webSocketContext.WebSocket;
            try
            {


                while (webSocket.State == WebSocketState.Open)
                {

                    ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[8192]);

                    WebSocketReceiveResult result = null;

                    using (var ms = new System.IO.MemoryStream())
                    {
                        do
                        {
                            result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
                            ms.Write(buffer.Array, buffer.Offset, result.Count);
                        }
                        while (!result.EndOfMessage);

                        ms.Seek(0, System.IO.SeekOrigin.Begin);

                        if (result.MessageType == WebSocketMessageType.Text)
                        {
                            using (var reader = new System.IO.StreamReader(ms, Encoding.UTF8))
                            {
                                var r = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                                var t = Newtonsoft.Json.JsonConvert.DeserializeObject<Datos>(r);
                                bool valid = true;
                                byte[] toBytes = Encoding.UTF8.GetBytes(""); ;

                                if (t != null)
                                {
                                    if (t.printer.Trim() == string.Empty)
                                    {
                                        var printers = "";
                                        foreach (var imp in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
                                        {
                                            printers += imp + "\n";
                                        }

                                        toBytes = Encoding.UTF8.GetBytes("No se Indicó la Impresora\nLas Impresoras disponibles son: " + printers);
                                        valid = false;
                                    }
                                    if (t.name.Trim() == string.Empty)
                                    {
                                        toBytes = Encoding.UTF8.GetBytes("No se Indicó el nombre del Documento");
                                        valid = false;
                                    }
                                    if (t.code == null)
                                    {
                                        toBytes = Encoding.UTF8.GetBytes("No hay datos para enviar a la Impresora");
                                        valid = false;
                                    }


                                    if (valid)
                                    {
                                        print.RawPrinter.SendStringToPrinter(t.printer, t.code, t.name);
                                        toBytes = Encoding.UTF8.GetBytes("Correcto...");
                                    }

                                    await webSocket.SendAsync(new ArraySegment<byte>(toBytes, 0, int.Parse(toBytes.Length.ToString())), WebSocketMessageType.Binary, result.EndOfMessage, CancellationToken.None);
                                }
                                else
                                {
                                    toBytes = Encoding.UTF8.GetBytes("Error...");
                                    await webSocket.SendAsync(new ArraySegment<byte>(toBytes, 0, int.Parse(toBytes.Length.ToString())), WebSocketMessageType.Binary, result.EndOfMessage, CancellationToken.None);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LogMessage(this, new LogMessageEventArgs(String.Format("Exception: {0} \nLinea:{1}", e, e.StackTrace)));
            }
            finally
            {
                if (webSocket != null)
                    webSocket.Dispose();
            }
        }
    }

    public class Datos
    {
        public string name { get; set; }
        public string code { get; set; }
        public string printer { get; set; } = "";
    }
}

raw Print:

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;

namespace print
{
    public class RawPrinter
    {
        // Structure and API declarions:
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public class DOCINFOA
        {
            [MarshalAs(UnmanagedType.LPStr)]
            public string pDocName;
            [MarshalAs(UnmanagedType.LPStr)]
            public string pOutputFile;
            [MarshalAs(UnmanagedType.LPStr)]
            public string pDataType;
        }
        [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)]
string szPrinter, ref IntPtr hPriknter, IntPtr pd);

        [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool ClosePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In(), MarshalAs(UnmanagedType.LPStruct)]
DOCINFOA di);

        [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndDocPrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartPagePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndPagePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, ref Int32 dwWritten);

        // SendBytesToPrinter()
        // When the function is given a printer name and an unmanaged array
        // of bytes, the function sends those bytes to the print queue.
        // Returns true on success, false on failure.
        public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount, string DocName = "")
        {
            Int32 dwError = 0;
            Int32 dwWritten = 0;
            IntPtr hPrinter = new IntPtr(0);
            DOCINFOA di = new DOCINFOA();
            bool bSuccess = false;
            // Assume failure unless you specifically succeed.
            di.pDocName = string.IsNullOrEmpty(DocName) ? "My C#.NET RAW Document" : DocName;
            di.pDataType = "RAW";

            // Open the printer.
            if (OpenPrinter(szPrinterName.Normalize(), ref hPrinter, IntPtr.Zero))
            {
                // Start a document.
                if (StartDocPrinter(hPrinter, 1, di))
                {
                    // Start a page.
                    if (StartPagePrinter(hPrinter))
                    {
                        // Write your bytes.
                        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, ref dwWritten);
                        EndPagePrinter(hPrinter);
                    }
                    EndDocPrinter(hPrinter);
                }
                ClosePrinter(hPrinter);
            }
            // If you did not succeed, GetLastError may give more information
            // about why not.
            if (bSuccess == false)
            {
                dwError = Marshal.GetLastWin32Error();
            }
            return bSuccess;
        }

        public static bool SendFileToPrinter(string szPrinterName, string szFileName)
        {
            // Open the file.
            FileStream fs = new FileStream(szFileName, FileMode.Open);
            // Create a BinaryReader on the file.
            BinaryReader br = new BinaryReader(fs);
            // Dim an array of bytes big enough to hold the file's contents.
            Byte[] bytes = new Byte[fs.Length];
            bool bSuccess = false;
            // Your unmanaged pointer.
            IntPtr pUnmanagedBytes = new IntPtr(0);
            int nLength = 0;

            nLength = Convert.ToInt32(fs.Length);
            // Read the contents of the file into the array.
            bytes = br.ReadBytes(nLength);
            // Allocate some unmanaged memory for those bytes.
            pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
            // Copy the managed byte array into the unmanaged array.
            Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
            // Send the unmanaged bytes to the printer.
            bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
            // Free the unmanaged memory that you allocated earlier.
            Marshal.FreeCoTaskMem(pUnmanagedBytes);
            return bSuccess;
        }
        public static bool SendStringToPrinter(string szPrinterName, string szString, string DocName = "")
        {
            IntPtr pBytes = default(IntPtr);
            Int32 dwCount = default(Int32);
            // How many characters are in the string?
            dwCount = szString.Length;
            // Assume that the printer is expecting ANSI text, and then convert
            // the string to ANSI text.
            pBytes = Marshal.StringToCoTaskMemAnsi(szString);
            // Send the converted ANSI string to the printer.
            SendBytesToPrinter(szPrinterName, pBytes, dwCount, DocName);
            Marshal.FreeCoTaskMem(pBytes);
            return true;
        }
    }
}

html页面:

<!DOCTYPE html>
<html>

<head>
</head>

<body ng-app="myapp">

    <div ng-controller="try as ctl">
        <input ng-model="ctl.ticket.nombre">

        <textarea ng-model="ctl.ticket.code"></textarea>

        <button ng-click="ctl.send()">Enviar</button>
    </div>


    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
    <script>
        var ws = new WebSocket("ws://localhost:2645/service");
        ws.binaryType = "arraybuffer";
        ws.onopen = function () {
            console.log('connection is opened!!!');
        };

        ws.onmessage = function (evt) {
            console.log(arrayBufferToString(evt.data))

        };

        ws.onclose = function () {
            console.log("Connection is Closed...")
        };

        function arrayBufferToString(buffer) {
            var arr = new Uint8Array(buffer);
            var str = String.fromCharCode.apply(String, arr); 

           return  decodeURIComponent(escape(str));
        }
        var app = angular.module('myapp', []);
        app.controller('try', function () {
            this.ticket= {nombre:'', estado:''}

            this.send = () => {
                var toSend= JSON.stringify(this.ticket);
                ws.send(toSend);
            }
        });
    </script>
</body>

</html>

然后从html发送一个ZPL代码(在textarea代码上写这个);

^XA
^FO200,50^BY2^B3N,N,80,Y,N^FD0123456789^FS
^PQ1^XZ