The JSPrintManager Razor Component
Important
Be sure that the JSPM App is installed and running! Please refer to the Client-side Configuration...
First Steps with JSPrintManager
❶ Be sure you've added the JSPrintManager Razor Component reference to your Blazor project
❷ Add the JSPrintManager service...
For Blazor Server:
Add the following statement at the top of your Startup file
using Neodynamic.Blazor;
Add the following line in the Startup's ConfigureServices method
services.AddJSPrintManager(); // JSPrintManager service
For Blazor WebAssembly:
Add the following statement at the top of your Startup file
using Neodynamic.Blazor;
Add the following line in the Program's Main method
builder.Services.AddJSPrintManager(); // JSPrintManager service
In both cases, add the following using
statement in the _Imports.razor file
@using Neodynamic.Blazor
❸ Basic Sample - Printing a JPG Image to Default Printer. (More Printer Types...)
Note
You can specify another file format like PNG, PDF, TXT, TIFF, etc if desired.
- Add a new Razor page and then copy/paste the following code. Read the comments to understand how JSPrintManager works...
@page "/"
@inject JSPrintManager JSPrintManager
<h1>Printing File to Default Printer...</h1>
@code {
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Handle OnStatusChanged event to detect any WSS status change
JSPrintManager.OnStatusChanged += () =>
{
// Status = Open means that JSPM Client App is up and running!
if (JSPrintManager.Status == JSPMWSStatus.Open)
{
// Create a ClientPrintJob
var cpj = new ClientPrintJob();
// Set Default Printer
cpj.ClientPrinter = new DefaultPrinter();
// Create a PrintFile
var myFile = new PrintFile()
{
FileContent = "https://neodynamic.com/temp/penguins300dpi.jpg",
FileContentType = FileSourceType.URL,
FileName = "MyFile.jpg",
Copies = 1
};
// Add the file to the print job
cpj.Files.Add(myFile);
// PRINT IT!!!
JSPrintManager.SendClientPrintJob(cpj);
}
};
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
❹ Basic Sample - Send RAW Printer Commands to Default Printer. (More Printer Types...)
Note
The raw printer commands you'll specify must be in the correct syntax required by the target printer! E.g. ZPL commands for Zebra, ESC/POS commands for EPSON, etc.
Important
Plain Text is NOT the same as RAW Printer Commands! Read more...
- Add a new Razor page and then copy/paste the following code. Read the comments to understand how JSPrintManager works...
@page "/"
@inject JSPrintManager JSPrintManager
<h1>Printing Raw Commands to Default Printer...</h1>
@code {
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Handle OnStatusChanged event to detect any WSS status change
JSPrintManager.OnStatusChanged += () =>
{
// Status = Open means that JSPM Client App is up and running!
if (JSPrintManager.Status == JSPMWSStatus.Open)
{
// Create a ClientPrintJob
var cpj = new ClientPrintJob();
// Set Default Printer
cpj.ClientPrinter = new DefaultPrinter();
// Set the RAW commands to send to the printer...
cpj.PrinterCommands = "RAW PRINTER COMMANDS HERE";
// PRINT IT!!!
JSPrintManager.SendClientPrintJob(cpj);
}
};
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
Full Sample Project
Please look at the source code of the JSPrintManager for Blazor Sample Projects at github
Starting JSPrintManager WebSocket Comm
The first thing to do in your project is to start the websocket comm between your website and the JSPM Client App. This should be done just once so adding it to the MainLayout.razor is a good place to start with if you will be using JSPrintManager in many pages. However, if you need to use JSPrintManager in a single page, then skip this step and just see how it was used in the samples above.
This is a sample template you could use in the MainLayout.razor
@inherits LayoutComponentBase
@inject JSPrintManager JSPrintManager
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
<div>
<strong>JSPM </strong><span>WebSocket Status </span>
@if (JSPrintManager.Status == JSPMWSStatus.Open)
{
<span class="badge badge-success">
<i class="fa fa-check" /> Open
</span>
}
else if (JSPrintManager.Status == JSPMWSStatus.Closed)
{
<span class="badge badge-danger">
<i class="fa fa-exclamation-circle" /> Closed!
</span>
}
else if (JSPrintManager.Status == JSPMWSStatus.Blocked)
{
<span class="badge badge-warning">
<i class="fa fa-times-circle" /> This Website is Blocked!
</span>
}
else if (JSPrintManager.Status == JSPMWSStatus.WaitingForUserResponse)
{
<span class="badge badge-warning">
<i class="fa fa-user-circle" /> Waiting for user response...
</span>
}
</div>
</div>
<div class="content px-4">
@Body
</div>
</div>
@code {
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Handle OnStatusChanged event to detect any WSS status change
JSPrintManager.OnStatusChanged += () =>
{
StateHasChanged();
};
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
Print Job Status/Trace
JSPrintManager allows you to get notified about any update on the ClientPrintJob you are sending to a given printer. The Print Job information retrieved will depend on the client OS and will be provided to you as a JSON Object.
The following sample is an extension of the Basic Sample - Printing a JPG Image to Default Printer sample shown above where the Print Job Status/Trace info is displayed in the page.
- Add a new Razor page and then copy/paste the following code. Read the comments to understand how JSPrintManager works...
@page "/"
@inject JSPrintManager JSPrintManager
@using System.Text
<h1>Printing file to Default Printer...</h1>
<h2>Job Status Trace</h2>
<textarea readOnly @bind="JobStatusTrace" rows="10" />
@code {
// Create a ClientPrintJob
private ClientPrintJob MyCPJ = new ClientPrintJob();
// Job Status trace buffer...
private string JobStatusTrace = "";
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Handle job status changes...
JSPrintManager.OnClientPrintJobStatusChanged += () =>
{
var jobStatusBuffer = JSPrintManager.ClientPrintJobStatusCache.Where(jobStatus => jobStatus.Id == MyCPJ.Id).ToArray();
var sb = new StringBuilder();
foreach (var entry in jobStatusBuffer)
{
sb.Append(entry.Data.ToString());
sb.Append("\n");
}
JobStatusTrace = sb.ToString();
StateHasChanged();
};
// Handle OnStatusChanged event to detect any WSS status change
JSPrintManager.OnStatusChanged += () =>
{
// Status = Open means that JSPM Client App is up and running!
if (JSPrintManager.Status == JSPMWSStatus.Open)
{
// Set Default Printer
MyCPJ.ClientPrinter = new DefaultPrinter();
// Set the RAW commands to send to the printer...
var myFile = new PrintFile()
{
FileContent = "https://neodynamic.com/temp/penguins300dpi.jpg",
FileContentType = FileSourceType.URL,
FileName = "MyFile.jpg",
Copies = 1
};
// Add the file to the print job
MyCPJ.Files.Add(myFile);
// PRINT IT!!!
JSPrintManager.SendClientPrintJob(MyCPJ);
}
};
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
Get Installed Printers
JSPrintManager allows you to get the list of installed printers available at the client machine. By "installed printers" it means the printers that are listed and installed under Windows, Linux or Mac OS.
There are two ways to get them through any JSPrintManager class instance:
- Call the TryGetPrinters() method, then handle the OnGetPrinters() event to get the list of printers name which will be available in the Printers property. Here's an example:
@page "/"
@inject JSPrintManager JSPrintManager
@if (JSPrintManager.Printers == null)
{
<h1>Getting installed printer...</h1>
<div class="spinner-border text-info" role="status">
<span class="sr-only">Please wait...</span>
</div>
}
else
{
<h1>Installed Printers</h1>
<div>@(String.Join(" | ", JSPrintManager.Printers))</div>
}
@code {
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Handle OnGetPrinters event...
JSPrintManager.OnGetPrinters += () =>
{
if (JSPrintManager.Printers != null &&
JSPrintManager.Printers.Length > 0)
{
// Display installed printers...
StateHasChanged();
}
else
{
Console.WriteLine("No printers found...");
}
};
// Handle OnStatusChanged event to detect any WSS status change
JSPrintManager.OnStatusChanged += () =>
{
// Status = Open means that JSPM Client App is up and running!
if (JSPrintManager.Status == JSPMWSStatus.Open)
{
//Try getting local printers...
JSPrintManager.TryGetPrinters();
}
};
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
- Call the GetPrinters method. Here's an example:
@page "/"
@inject JSPrintManager JSPrintManager
@if (_printers == null)
{
<input type="button" value="Get installed printers..." @onclick="GetClientPrinters" />
}
else
{
<h1>Installed Printers</h1>
<div>@(String.Join(" | ", _printers))</div>
}
@code {
private string[] _printers = null;
async void GetClientPrinters()
{
// Status = Open means that JSPM Client App is up and running!
if (JSPrintManager.Status == JSPMWSStatus.Open)
{
//Get local printers...
_printers = await JSPrintManager.GetPrinters();
StateHasChanged();
}
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
Get Installed Printers including detailed information
JSPrintManager allows you to get the list of installed printers available at the client machine including detailed information like DPI Resolution, PortName, "Is Connected", "Is Shared", "Is Local", "Is Network", as well as the list of supported Papers and list of trays/bins. By "installed printers" it means the printers that are listed and installed under Windows, Linux or Mac OS.
There are two ways to get them through any JSPrintManager class instance:
- Call the TryGetPrintersInfo() method, then handle the OnGetPrintersInfo() event to get the list of printers name which will be available in the PrintersInfo collection property. Here's an example:
@page "/"
@inject JSPrintManager JSPrintManager
@if (JSPrintManager.PrintersInfo == null)
{
<h1>Getting installed printer info...</h1>
<div class="spinner-border text-info" role="status">
<span class="sr-only">Please wait...</span>
</div>
}
else
{
<h1>Installed Printers</h1>
@foreach (var @printerInfo in JSPrintManager.PrintersInfo)
{
<div>@(String.Format("Name: {0} - Port: {1} - DPI: {2}", new object[] { printerInfo.Name, printerInfo.Port, printerInfo.XDPI }))</div>
}
}
@code {
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Handle OnGetPrintersInfo event...
JSPrintManager.OnGetPrintersInfo += () =>
{
if (JSPrintManager.PrintersInfo != null &&
JSPrintManager.PrintersInfo.Length > 0)
{
// Display installed printers...
StateHasChanged();
}
else
{
Console.WriteLine("No printers found...");
}
};
// Handle OnStatusChanged event to detect any WSS status change
JSPrintManager.OnStatusChanged += () =>
{
// Status = Open means that JSPM Client App is up and running!
if (JSPrintManager.Status == JSPMWSStatus.Open)
{
//Try getting local printers info...
JSPrintManager.TryGetPrintersInfo();
}
};
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
- Call the GetPrintersInfo method. Here's an example:
@page "/"
@inject JSPrintManager JSPrintManager
@if (_printersInfo == null)
{
<input type="button" value="Get installed printers info..." @onclick="GetClientPrintersInfo" />
}
else
{
<h1>Installed Printer</h1>
@foreach (var @printerInfo in _printersInfo)
{
<div>@(String.Format("Name: {0} - Port: {1} - DPI: {2}", new object[] { printerInfo.Name, printerInfo.Port, printerInfo.XDPI }))</div>
}
}
@code {
private PrinterInfo[] _printersInfo = null;
async void GetClientPrintersInfo()
{
// Status = Open means that JSPM Client App is up and running!
if (JSPrintManager.Status == JSPMWSStatus.Open)
{
//Get local printers info...
_printersInfo = await JSPrintManager.GetPrintersInfo();
StateHasChanged();
}
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
Printers Watcher (Windows Only)
JSPrintManager provides you a Printers Watcher allowing you to detect when a new printer is added, when a printer is removed/deleted, and when any changes or modifications are done on any printers available at the client machine. At the moment this feature is available in Windows clients only.
The Printers Watcher can be startes by calling the StartPrintersWatcher method and handling the OnPrintersEvent event of any JSPrintManager class instance.
Printing Common File Formats
In addition to print native commands, you can also use JSPrintManager solution to send and print common file formats like PDF, TIF, TXT, DOC, XLS, JPG, PNG, etc.
The Print File feature has the following requirements:
File Format | Windows Clients | Linux & Mac Clients |
---|---|---|
DOC, DOCX | Microsoft Word is required | LibreOffice is required |
XLS, XLSX | Microsoft Excel is required | LibreOffice is required |
Natively supported! | Natively supported! | |
TIF | Natively supported! | Natively supported! |
TXT | Natively supported! | Natively supported! |
JPEG | Natively supported! | Natively supported! |
PNG | Natively supported! | Natively supported! |
BMP | Natively supported! | Natively supported! |
Printer Support | You can print files to local installed printers ONLY! Parallel, Serial and IP/Ethernet printers are NOT supported. | You can print files to any installed printers through CUPS system. |
To spacify a given file for printing, then create an instance of the many PrintFile classes. Please Browse the API Reference documentation.
Printing Multiple Files to the same Printer
The following sample code will print two files to the Default printer. (More Printer Types...)
- Add a new Razor page and then copy/paste the following code. Read the comments to understand how JSPrintManager works...
@page "/"
@inject JSPrintManager JSPrintManager
<h1>Printing Files to Default Printer...</h1>
@code {
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Handle OnStatusChanged event to detect any WSS status change
JSPrintManager.OnStatusChanged += () =>
{
// Status = Open means that JSPM Client App is up and running!
if (JSPrintManager.Status == JSPMWSStatus.Open)
{
// Create a ClientPrintJob
var cpj = new ClientPrintJob();
// Set Default Printer
cpj.ClientPrinter = new DefaultPrinter();
// Create a PrintFile for an image file
var myFile = new PrintFile()
{
FileContent = "https://neodynamic.com/temp/penguins300dpi.jpg",
FileContentType = FileSourceType.URL,
FileName = "MyFile.jpg",
Copies = 1
};
// Create a PrintFilePDF for a PDF file
var myFilePDF = new PrintFilePDF()
{
FileContent = "https://neodynamic.com/temp/LoremIpsum.pdf",
FileContentType = FileSourceType.URL,
FileName = "MyFile.pdf",
Copies = 1
};
// Add the files to the print job
cpj.Files.Add(myFile);
cpj.Files.Add(myFilePDF);
// PRINT THEM!!!
JSPrintManager.SendClientPrintJob(cpj);
}
};
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
Printing Multiple Files to Different Printers
The following sample code will print files to different printers
- Add a new Razor page and then copy/paste the following code. Read the comments to understand how JSPrintManager works...
@page "/"
@inject JSPrintManager JSPrintManager
<h1>Printing Multiple Files to Different Printers...</h1>
@code {
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// Handle OnStatusChanged event to detect any WSS status change
JSPrintManager.OnStatusChanged += () =>
{
// Status = Open means that JSPM Client App is up and running!
if (JSPrintManager.Status == JSPMWSStatus.Open)
{
// Create a ClientPrintJob for the Image
var cpj1 = new ClientPrintJob();
// Set target Printer
cpj1.ClientPrinter = new InstalledPrinter(){PrinterName = "Printer1"};
// Create a PrintFile for an image file
var myFile = new PrintFile()
{
FileContent = "https://neodynamic.com/temp/penguins300dpi.jpg",
FileContentType = FileSourceType.URL,
FileName = "MyFile.jpg",
Copies = 1
};
// Add the file to the first print job
cpj1.Files.Add(myFile);
// Create a ClientPrintJob for the PDF
var cpj2 = new ClientPrintJob();
// Set target Printer
cpj2.ClientPrinter = new InstalledPrinter(){PrinterName = "Printer2"};
// Create a PrintFilePDF for a PDF file
var myFilePDF = new PrintFilePDF()
{
FileContent = "https://neodynamic.com/temp/LoremIpsum.pdf",
FileContentType = FileSourceType.URL,
FileName = "MyFile.pdf",
Copies = 1
};
// Add the file to the second print job
cpj2.Files.Add(myFilePDF);
// PRINT THEM!!!
JSPrintManager.SendClientPrintJob(new List<ClientPrintJob>(){cpj1, cpj2});
}
};
// Start WebSocket comm
JSPrintManager.Start();
}
base.OnAfterRender(firstRender);
}
}
Printer Commands (RAW Data Printing)
The printer commands you want to send to the client printer is specified through the PrinterCommands property of the ClientPrintJob object.
Some Printer Command/Programming Languages feature non-printable or non-human-readable characters in their syntax. Common samples are the ESC/P language which uses ASCII Dec 27 (ESC), ASCII Dec 10 (LF), ASCII Dec 13 (CR), etc; thermal printer languages like Zebra ZPL which sometimes needs to specify ASCII Dec 29 (GS), ASCII Dec 30 (RS), ASCII Dec 4 (EOT), etc.
These non-printable chars can be specified in Hexadecimal notation within the string commands.
For example, suppose you need to send ESC/P codes for "Set page length in inches" which syntax is as follows: [ESC] C [NUL] n
Where:
- [ESC]: is ASCII Hex 1B
- C: is ASCII Hex 43
- [NUL]: is ASCII 00
- n: is a number in the range 1 < n < 22
Then to specify this command as a string and using the Hexadecimal notation:
//set the commands to send to the printer
cpj.PrinterCommands = "0x1B C 0x00 5";
Client Printer Types
The Client Printer is specified through the ClientPrinter property and it accepts an object that should be an instance of any of the following ClientPrinter-derived classes:
- DefaultPrinter
- UserSelectedPrinter
- InstalledPrinter
- ParallelPortPrinter
- SerialPortPrinter
- NetworkPrinter
DefaultPrinter
The DefaultPrinter allows you to print to the client's printer which is set up as the "default printer". The printing is performed without displaying any dialog to the user. Here is a snippet code of how to use this option:
// ...
var cpj = new ClientPrintJob();
cpj.ClientPrinter = new DefaultPrinter();
// ...
UserSelectedPrinter
The UserSelectedPrinter allows you to let the user to dynamically select which printer he/she wants to use by displaying a Print Dialog box. That print dialog will list all the installed printers in the user's machine. Here is a snippet code of how to use this option:
// ...
var cpj = new ClientPrintJob();
cpj.ClientPrinter = new UserSelectedPrinter();
// ...
InstalledPrinter
The InstalledPrinter allows you to specify the "Printer Name" of an installed printer at the client machine. By "installed" it means, a printer which is listed in the Printers section of Windows, Linux or Mac OS. Those printers are generally installed by using a driver provided by the manufacturer.
Note
For Raw printing, installing the "Generic / Text Only" driver that comes with Windows OS (and similar driver on Linux & Mac OS) is sufficient in many cases. The "Generic / Text Only" driver is also useful when you cannot get the original driver from the manufacturer because it does not support a given version of Windows or the printer is too old, etc.
Note
You can also specify the Tray Name (TrayName prop) as well as the Paper Name (PaperName prop) to be used by the specified printer when printing the following file formats: PNG, JPG, BMP, TXT, TIF & PDF
So, suppose the user has a printer installed which name is "MyLocalPrinter". Here is a snippet code of how to use this option:
//...
var cpj = new ClientPrintJob();
cpj.ClientPrinter = new InstalledPrinter(){PrinterName = "MyLocalPrinter"};
// ...
Special case for Shared Network printers: When the user has an installed printer which is a Shared Network Printer (i.e. a printer attached to another computer on the network), then you can use the InstalledPrinter option to specify such kind of printer. The correct way to specify the printer's name in these cases is by using the UNC (Universal Naming Convention) name/path to reach the printer.
So, suppose the user has a network printer installed which UNC path is "\anotherPC\CoolBrandPrinter". Here is a snippet code of how to use this option:
//...
var cpj = new ClientPrintJob();
cpj.ClientPrinter = new InstalledPrinter(){PrinterName = "\\\\anotherPC\\CoolBrandPrinter"};
// ...
ParallelPortPrinter
The ParallelPortPrinter allows you to specify the parallel port (LPT) of the client machine that the printer is connected to. The client does not need to install the printer through Windows OS. However, a valid LPT port needs to be available and the printer connected to such port through a Centronics interface.
Note
For Linux & Mac OS, Parallel Port printers must be installed through CUPS and then set the assigned printer name through the InstalledPrinter option.
Here is a snippet code of how to use this option:
//...
var cpj = new ClientPrintJob();
cpj.ClientPrinter = new ParallelPortPrinter(){PrinterName = "LPT1"};
// ...
SerialPortPrinter
The SerialPortPrinter allows you to specify the serial port (RS-232) settings of the client printer. The client does not need to install the printer through Windows OS. However, a valid serial port needs to be available and the printer connected to such port. Please refer to the client's printer manual for details about the serial port settings.
Note
For Linux & Mac OS, Serial RS232 Port printers must be installed through CUPS and then set the assigned printer name through the InstalledPrinter option.
Here is a snippet code of how to use this option:
//...
var cpj = new ClientPrintJob();
cpj.ClientPrinter = new SerialPortPrinter(){
PortName="COM1",
BaudRate=9600,
Parity=SerialPortParity.None,
StopBits=SerialPortStopBits.One,
DataBits=8,
FlowControl=SerialPortHandshake.XOnXOff
};
// ...
NetworkPrinter
The NetworkPrinter allows you to specify a TCP/IP Ethernet-enabled printer that can be reached from the client machine. The client printer in this case can be specified by using the IP address or DNS name as well as the port number.
Note
For Linux & Mac OS, IP/Ethernet printers should be installed through CUPS and then set the assigned printer name through the InstalledPrinter option.
Here is a snippet code of how to use this option:
//...
var cpj = new JSPM.ClientPrintJob();
cpj.ClientPrinter = new NetworkPrinter(){Port=9100, IPAddress="10.0.0.8"};
// ...
Scanning Documents & Images
JSPrintManager enables any web page to scan documents and images through any TWAIN/SANE compatible devices available at the client side. JSPrintManager allows you to list the installed scanners available at the client machine and specify scan settings like the resolution and output quality (dpi), the desired pixel mode (Grayscale or full Color), Duplex, ADF, as well as the output image format (JPG/JPEG or PNG). Please look at the source code of the JSPrintManager for Blazor Sample Projects at github for a sample code about this topic.
BIDI Serial Communication
JSPrintManager supports Bidirectional (BIDI) Serial Port Communication from Javascript allowing you to Send/Write & Receive/Read data strings to any RS-232, COM & TTY port available on the client system. Please Browse the API Reference documentation.
Detecting JSPM Client App
The JSPM Client App utility (that each user must have it installed) is a key component of the JSPrintManager for Blazor solution. So, it is very important you can detect somehow whether JSPM App is already installed and running at the client machine from your Website. Please look at a sample code above...
API Reference
Browse the API Reference documentation
Articles & Code Samples
Browse the JSPrintManager for Blazor Articles & Code Samples for other printing & scanning topics including advanced topics like printing password-protected docs and more!
Sample Project & Online Demo
- Try the JSPrintManager for Blazor Solution through our Online Demo
- Look at the source code of the JSPrintManager for Blazor Sample Website at github