Подтвердить что ты не робот

Печать штрих-кодов с веб-страницы на принтер Zebra

Мы пытаемся распечатать штрих-коды с веб-страницы на нашем принтере Zebra.

Мне интересно, есть ли способ распечатать их, используя собственный шрифт принтера, возможно, используя веб-шрифты или если я знал, что используется имя шрифта?

Я пытаюсь использовать генераторы php barcode, которые в основном генерируют изображения, содержащие штрих-код. На самом деле я уже несколько дней пробовал этот подход без успеха.

Проблема заключается в том, что я печатаю их, которые не читаются сканерами. Я попытался изменить разрешение изображения в соответствии с разрешением принтера (203dpi), также попытался сыграть с размером и форматом изображения, но штрих-коды после печати еще не могут быть отсканированы.

У кого-нибудь есть опыт с этим?

Принтер: Zebra TLP 2844

Штрих-коды, требуемые для каждой страницы:

  • 01 Code39 по горизонтали (можно сканировать только при печати по очень определенному размеру и в браузере)
  • 01 Code128 vertical (все еще не может заставить его работать, печать всегда очень размыта и не будет отсканирована)

===========

Я немного поработал, я узнал, что этот принтер поддерживает язык EPL2, поэтому я пытаюсь использовать его для печати штрих-кодов.

Сначала мне нужно было включить режим сквозной передачи, я сделал это в меню "Параметры принтера" > "Расширенная настройка" > "Разное".

Теперь я могу безошибочно печатать штрих-коды с помощью встроенного шрифта принтера: D с помощью этой команды:

ZPL: B10,10,0,1,2,2,60, N, "TEXT-GOES-HERE" : ЗПЛ

Но я могу только печатать его из "Блокнота", я все еще не могу напечатать это из браузера... Вероятно, проблема с заменой LF на CR + LF...

Как преодолеть эту проблему?

===========

Ярлык, который я пытаюсь напечатать, на самом деле имеет немного текста перед штрих-кодом, а некоторые таблицы html его форматируют. Поэтому мне нужно сначала распечатать это, и в середине мне нужно вставить яркую метку, а затем добавить еще текст.

Поэтому я не могу использовать чистый EPL2 для печати всего, мне интересно, могу ли я использовать некоторые из html + EPL2 + html для достижения своей цели или это не разрешено?? =/

4b9b3361

Ответ 1

Вы сталкиваетесь с несколькими препятствиями:

1) Когда вы печатаете через установленный OS драйвер принтера, драйвер принтера пытается передать данные, которые ему отправлены, и (повторно) растрировать или масштабировать его для устройства вывода (принтер Zebra). Поскольку принтер имеет относительно низкое разрешение при 203dpi, то это не занимает слишком много для масштабирования, которое драйвер печати должен сделать для того, чтобы он потерял некоторую целостность в качестве штрих-кода. Вот почему штрих-коды, созданные с использованием прямых команд ZPL, намного более надежны.

2) Из-за безопасности, которую веб-браузеры целенаправленно предоставляют, не разрешая доступ к клиентскому компьютеру, вы не можете напрямую общаться с подключенным к клиенту принтером. Эта песочница - это то, что помогает защитить пользователей от вредоносных программ, чтобы нецензурные веб-сайты не могли делать такие вещи, как запись файлов на клиентский компьютер, или отправлять вывод напрямую на такие устройства, как принтеры. Таким образом, вы не можете напрямую отправлять команды ZPL через браузер на подключенный к клиенту принтер.

Однако есть способ сделать то, что вы описали. Необходимые шаги обычно будут полезны только в том случае, если у вас есть определенный контроль над клиентским компьютером, который обращается к сайту, который пытается распечатать на принтеры Zebra. Например, это будет использоваться только машинами в сети вашей компании или клиентами, которые хотят установить небольшое приложение, которое вам нужно написать. Для этого вам нужно будет посмотреть следующие шаги:

A) Вы должны создать свой собственный тип MIME. Это в основном просто любое имя, которое вы хотите использовать, которое не будет сталкиваться с любыми зарегистрированными MIME-типами.

B) Далее вы определите расширение имени файла, которое будет отображаться на ваш пользовательский тип MIME. Для этого вам, как правило, потребуется настроить веб-сервер (шаги для этого зависят от того, какой веб-сервер вы используете), чтобы разрешить новый тип MIME, который вы хотите определить, и какое расширение файла используется для этих типов файлов.

C) Затем в своем веб-приложении, когда вы хотите вывести данные ZPL, вы пишете его в файл, используя расширение имени файла, которое сопоставляется с вашим новым типом MIME. Затем, как только файл сгенерирован, вы можете либо предоставить ему ссылку HTML, либо перенаправить клиентский браузер в файл. Вы можете проверить, правильно ли ваш файл работает в данный момент, вручную скопировав файл, который вы создали, прямо на исходный порт принтера.

D) Затем вам нужно написать небольшое приложение, которое можно установить на клиенте. Когда приложение установлено, вам необходимо зарегистрировать его как действующее приложение-потребитель для вашего пользовательского типа MIME. Если браузер обнаруживает, что есть установленное приложение для файла с указанным типом MIME, он просто записывает файл во временный каталог на клиентской машине, а затем пытается запустить приложение с тем же зарегистрированным типом MIME с временным файлом как параметр для приложения. Таким образом, ваше приложение теперь просто считывает файл, который передал браузер, а затем пытается сбросить его непосредственно на принтер.

Это обзор того, что вам нужно сделать, чтобы выполнить то, что вы описываете. Некоторые из конкретных шагов будут зависеть от того, какой тип веб-сервера вы используете, и о том, какие ОС являются вашими клиентами. Но это обзор высокого уровня, который позволит вам выполнить то, что вы пытаетесь сделать.

Ответ 2

Если вы захотите загрузить java-апплет, qz-print (ранее jzebra) может делать то, что вы описываете, и прекрасно работает с LP2844, упомянутым в комментариях.

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

Ответ 3

Что мы сделали для нашего веб-приложения:

1) Загрузите бесплатное приложение для печати http://www.lerup.com/printfile/

"PrintFile - это бесплатная программа для MS Windows, которая позволит вам быстро и легко печатать файлы. Программа распознает простой текст, PostScript, Encapsulated PostScript (EPS) и двоичные форматы. Использование этой программы может сэкономить вам много бумаги и тем самым также экономить ценные природные ресурсы".

При первом запуске PrintFile перейдите к дополнительным параметрам и включите "отправить на принтер напрямую".

2) Установите принтер ZEBRA в Windows в качестве универсального текстового принтера.

2) Создайте файл file.prt в веб-приложении, которое является просто текстовым файлом EPL.

3) Двойной щелчок по загруженному файлу мгновенно распечатает штрих-код. Работает как шарм. Вы даже можете настроить PrintFile, чтобы вы даже не видели gui.

Ответ 4

Я развиваю нечто подобное здесь. Мне нужно напечатать в LP2844 из моего webapp. Проблема в том, что мой webapp находится на удаленном сервере в облаке (Amazon EC2), и принтер будет находиться на складе.

Мое решение: Webapp генерирует код EPL2 для ярлыка со штрих-кодами, а затем публикует заголовок сообщение PubNub. Я написал небольшую программу на С#, которая работает на компьютере, на котором подключен принтер. Программа получает сообщение, а затем отправляет код на принтер.

Ответ 5

Вы также можете отправить команды ZPL в текстовый файл (вы можете упаковать несколько ярлыков в один файл) и открыть пользователя и распечатать файл через блокнот Windows. Единственное предостережение в том, что они должны удалить верхний и нижний колонтитулы по умолчанию (Файл → Настройка страницы).

Немного для обучения пользователей, но может быть приемлемым, если у вас нет контроля над клиентскими машинами.

Ответ 6

Я следил за идеей, предложенной "Tres Finocchiaro" в моей заявке на основе:

  • ASP.NET 4.0
  • IIS
  • Chrome, IExplorer, Firefox
  • Zebra TLP 2844
  • Протокол EPL

К сожалению, jzebra нуждается в некоторых улучшениях, чтобы работать исправно из-за проблем безопасности текущего браузера.

Установка jzebra

Downlod jzebdra и из каталога dist я копирую в ваш каталог (например, mydir):

  • Веб
    • MYDIR
      • JS
        • ..
        • deployJava.js
      • Lib
        • ..
      • Кв-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 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>

предоставленный код основан на "jzebra_installation/dist/sample.html".

Ответ 7

попробуйте создать 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 Печать:

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

затем отправьте код ZPL из html (напишите это на textarea code);

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