I am trying to build a java applet which prints a PDF file and sends it to a label printer rather than the default. I explored desktop.print but couldn't work out how to specify the printer.
This is the code I have, i've tried to look for solutions but have ended stuck. I have signed the applet and the error it gives me it just says application error 0
import java.io.*;
import java.net.*;
import javax.swing.*;
import java.awt.print.*;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
public class printPDF extends JApplet {
public void init(){
String uri = System.getProperty("user.home") + "\\jobbase\\print.pdf";
DocFlavor flavor = DocFlavor.INPUT_STREAM.PDF;
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(new PrinterName("label", null));
aset.add(new Copies(1));
PrintService[] pservices =
PrintServiceLookup.lookupPrintServices(flavor, aset);
if (pservices.length > 0) {
DocPrintJob printJob = pservices[0].createPrintJob();
try{
FileInputStream fis = new FileInputStream(uri);
Doc doc = new SimpleDoc(fis, flavor, null);
try {
printJob.print(doc, aset);
} catch (PrintException e) {
System.err.println(e);
}
} catch(IOException ioe){
ioe.printStackTrace(System.out);
}
} else {
System.err.println("No suitable printers");
}
}
}
You can't just send the PDF to the printer unless you know it can understand it. Most of the time you need to rasterize it on the client. I write a blog article explaining the options at http://www.jpedal.org/PDFblog/2010/01/printing-pdf-files-from-java/
If you know the name of the printer you can achieve this. In one client I needed silent printing: if a printer named appprinter was present, I used it, if not I tried with the default. This worked out fine.
For printing I use ICEPDF.
Kate: thanks for the suggestion, honestly IcePDF is pretty straight forward, this example is included in the source code that you can download from the link above. In order to obtain the PrinterService (aka printer) needed you can delete all the user input requested by keyboard and just use the one with the name you want.
So, in version 5.0.5: [install-folder]/examples/printservices/PrintService.java
delete user selection of printservice: lines 106 to 155
add instead:
PrintService selectedService=null;
for (int j=0;j<services.length;j++) {
if ("myprintername".equalsIgnoreCase(services[j].getName())) {
selectedService=aux[j];
}
}
Hope now it is more useful.
Best regards.
Related
I am stuck at this now. I have checked almost every popular question on SO site regarding Java Print API to print HTML files (with third-party libraries such as Flying Saucer, iText, CSSBox, etc). But still couldn't get it worked at my end yet.
Here are the links of my previous questions:
https://stackoverflow.com/questions/28106757/java-print-api-prints-html-with-huge-size
How to print HTML and not the code using Java Print API?
Basically I am trying to print the HTML file that contains some CSS with <style> tag. This CSS has classes applied for <table> and <p> tags for example. I cannot change CSS code inside HTML as it should be viewed exactly with this style in browser.
Below is my program
import java.awt.print.PrinterException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashPrintServiceAttributeSet;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.standard.PrinterName;
import javax.swing.JEditorPane;
public class Print {
public static void main(String[] args) throws PrintException {
String printerName = "\\\\network-path\\myPrinter";
String fileName = "C:\\log\\myLog.html";
URL url = null;
try {
url = (new File(fileName)).toURI().toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
}
JEditorPane editorPane = new JEditorPane();
editorPane.setEditable(false);
if (url != null) {
try {
editorPane.setPage(url);
} catch (IOException e) {
System.err.println("Attempted to read a bad URL: " + url);
}
} else {
System.err.println("Couldn't find file: " + fileName);
}
PrintServiceAttributeSet printServiceAttributeSet = new HashPrintServiceAttributeSet();
printServiceAttributeSet.add(new PrinterName(printerName, null));
PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, printServiceAttributeSet); // list of printers
PrintService printService = printServices[0];
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
Copies copies = new Copies(1);
pras.add(copies);
pras.add(OrientationRequested.PORTRAIT);
pras.add(MediaSizeName.ISO_A4);
try {
editorPane.print(null, null, false, printService, pras, false);
} catch (PrinterException e) {
throw new PrintException("Print error occurred:" + e.getMessage());
}
}
}
The problem is above code works and I get good print of the above HTML with proper CSS styling. But it just scales up. When the said HTML is opened in IE it looks different and when it is printed by the code what I get is different. I would prefer the print to be same as it is viewed in IE.
I also tried to get it done by passing SimpleDoc object to the printer. My printService supports below formats:
image/gif [B
image/gif java.io.InputStream
image/gif java.net.URL
image/jpeg [B
image/jpeg java.io.InputStream
image/jpeg java.net.URL
image/png [B
image/png java.io.InputStream
image/png java.net.URL
application/x-java-jvm-local-objectref java.awt.print.Pageable
application/x-java-jvm-local-objectref java.awt.print.Printable
application/octet-stream [B
application/octet-stream java.net.URL
application/octet-stream java.io.InputStream
But nothing works with SimpleDoc. I then tried converting HTML to .png using CSSBox. It works but for multipage HTML, generated image is shrunk and is not viewable for printing. With Flying Saucer and iText version 2.0.8 I get NoSuchMethodError. Also even if I get it worked (by compiling the source against the said iText version) the output is broken.
Can someone please help? I would prefer to stick to Java Print API than using any third-party. Am I missing something when using SimpleDoc object approach? What settings need to be set to print above HTML using SimpleDoc object and available printService formats.
I have images of codes that I want to decode. How can I use zxing so that I specify the image location and get the decoded text back, and in case the decoding fails (it will for some images, that's the project), it gives me an error.
How can I setup zxing on my Windows machine? I downloaded the jar file, but I don't know where to start. I understand I'll have to create a code to read the image and supply it to the library reader method, but a guide how to do that would be very helpful.
I was able to do it. Downloaded the source and added the following code. Bit rustic, but gets the work done.
import com.google.zxing.NotFoundException;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.Reader;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.Result;
import com.google.zxing.LuminanceSource;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.util.*;
import com.google.zxing.qrcode.QRCodeReader;
class qr
{
public static void main(String args[])
{
Reader xReader = new QRCodeReader();
BufferedImage dest = null;
try
{
dest = ImageIO.read(new File(args[0]));
}
catch(IOException e)
{
System.out.println("Cannot load input image");
}
LuminanceSource source = new BufferedImageLuminanceSource(dest);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Vector<BarcodeFormat> barcodeFormats = new Vector<BarcodeFormat>();
barcodeFormats.add(BarcodeFormat.QR_CODE);
HashMap<DecodeHintType, Object> decodeHints = new HashMap<DecodeHintType, Object>(3);
decodeHints.put(DecodeHintType.POSSIBLE_FORMATS, barcodeFormats);
decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
Result result = null;
try
{
result = xReader.decode(bitmap, decodeHints);
System.out.println("Code Decoded");
String text = result.getText();
System.out.println(text);
}
catch(NotFoundException e)
{
System.out.println("Decoding Failed");
}
catch(ChecksumException e)
{
System.out.println("Checksum error");
}
catch(FormatException e)
{
System.out.println("Wrong format");
}
}
}
The project includes a class called CommandLineRunner which you can simply call from the command line. You can also look at its source to see how it works and reuse it.
There is nothing to install or set up. It's a library. Typically you don't download the jar but declare it as a dependency in your Maven-based project.
If you just want to send an image to decode, use http://zxing.org/w/decode.jspx
I've a JasperReports report to be printed on landscape mode on a duplex printer. On this I've to support PCL5 and PCL6 printing drivers.
Searching on the internet, I discovered the following code snippet to do this job:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.print.PrintService;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.Sides;
public class PrintingTest {
public static void main(String[] args) {
try {
//This are for configuration purpose
String orientation = "LANDSCAPE";
String duplexMode = "LONG_EDGE";
int pageOrientation = 0;
PrintRequestAttributeSet atr = new HashPrintRequestAttributeSet();
if ("Landscape".equals(orientation)) {
atr.add(OrientationRequested.LANDSCAPE);
pageOrientation = PageFormat.LANDSCAPE;
} else if ("Reverse_Landscape".equals(orientation)) {
atr.add(OrientationRequested.REVERSE_LANDSCAPE);
pageOrientation = PageFormat.REVERSE_LANDSCAPE;
} else {
atr.add(OrientationRequested.PORTRAIT);
pageOrientation = PageFormat.PORTRAIT;
}
if ("LONG_EDGE".equals(duplexMode)) {
atr.add(Sides.TWO_SIDED_LONG_EDGE);
} else {
atr.add(Sides.TWO_SIDED_SHORT_EDGE);
}
//Printing to the default printer
PrintService printer = javax.print.PrintServiceLookup
.lookupDefaultPrintService();
//Creating the printing job
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintService(printer);
Book book = new Book();
PageFormat pageFormat = printJob.defaultPage();
pageFormat.setOrientation(pageOrientation);
// Appending a exampledocument to the book
book.append(new ExampleDocument(), pageFormat);
// Appending another exampledocument to the book
book.append(new ExampleDocument(), pageFormat);
// Setting the Pageable to the printjob
printJob.setPageable(book);
try {
// Here a could show the print dialog
// printJob.printDialog(atr);
// Here I pass the previous defined attributes
printJob.print(atr);
} catch (Exception PrintException) {
PrintException.printStackTrace();
}
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
public static final int MARGIN_SIZE = 72;
private static class ExampleDocument implements Printable {
public int print(Graphics g, PageFormat pageFormat, int page) {
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pageFormat.getImageableX(),
pageFormat.getImageableY());
// Only on the first two documents...
if (page <= 1) {
// Prints using one inch margin
g2d.drawString("Printing page " + page + " - duplex...",
MARGIN_SIZE, MARGIN_SIZE);
return (PAGE_EXISTS);
}
return (NO_SUCH_PAGE);
}
}
}
This works fine on PCL6, but, when tested on PCL5, I noticed that LONG_EDGE and SHORT_EDGE rules are simple ignored. And that in both cases the job is sent as LONG_EDGE. This would not be a problem, except that Java AWT printing API resolves landscape printing by turning all pages 90ยบ anti-clockwise causing the impression that it was printed on SHORT_EDGE mode.
Obs: I was able to print correctly with both configuration, SHORT_EDGE and LONG_EDGE, in portrait and in landscape, by using the SWT API. But I'm not able to convert the jasper printing request in a SWT compatible printing request.
My question is: has anybody ever confronted this situation? Which solution was given to it?
From my observation I've found these possible solutions:
Instead of letting the AWT turn the page and send a portrait print request, force it to send it as a landscape printing request;
Find a way to, when the page is in landscape mode, invert LONG_EDGE and SHORT_EDGE commands. Observe that for this one I would be obligated to correct the problem in which both are treated as LONG_EDGE requests.
Convert the JasperReports to use SWT printing API.
Not sure it helps but I had this issue 6 years ago and the only solution was to use the printer's (Xerox) capability to receive the printing directives through an .xpf file. Example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xpif SYSTEM "xpif-v02012.dtd">
<xpif cpss-version="2.01" version="1.0" xml:lang="en">
<xpif-operation-attributes>
<job-name syntax="name" xml:lang="en" xml:space="preserve">job name</job-name>
<requesting-user-name syntax="name" xml:space="preserve">domain user</requesting-user-name>
</xpif-operation-attributes>
<job-template-attributes>
<copies syntax="integer">1</copies>
<finishings syntax="1setOf">
<value syntax="enum">3</value>
</finishings>
<job-recipient-name syntax="name" xml:lang="en-US" xml:space="preserve">domain user</job-recipient-name>
<job-save-disposition syntax="collection">
<save-disposition syntax="keyword">none</save-disposition>
</job-save-disposition>
<media-col syntax="collection">
<media-type syntax="keyword">stationery</media-type>
<media-hole-count syntax="integer">0</media-hole-count>
<media-color syntax="keyword">blue</media-color>
<media-size syntax="collection">
<x-dimension syntax="integer">21000</x-dimension>
<y-dimension syntax="integer">29700</y-dimension>
</media-size>
</media-col>
<orientation-requested syntax="enum">3</orientation-requested>
<sheet-collate syntax="keyword">collated</sheet-collate>
<sides syntax="keyword">one-sided</sides>
<x-side1-image-shift syntax="integer">0</x-side1-image-shift>
<y-side1-image-shift syntax="integer">0</y-side1-image-shift>
</job-template-attributes>
</xpif>
which was sent to the printer along with the file needed to be printed.
The code below sends data to a printer however, while it reaches the printer queue it comes back with a Unable to convert PostScript file. I thought that this would be overcome by specifying the flavor but this is not the case
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.standard.PrinterName;
public class New1 {
public static void main(String[] args) {
try {
String s = "Hello";
// byte[] by = s.getBytes();
DocFlavor flavor = DocFlavor.STRING.TEXT_PLAIN;
PrintService pservice = PrintServiceLookup.lookupDefaultPrintService();
DocPrintJob job = pservice.createPrintJob();
Doc doc = new SimpleDoc(s, flavor, null);
job.print(doc, null);
} catch (PrintException e) {
e.printStackTrace();
}
}
}
Using only JPS you will have problems with Mac.
My suggestion is use Java 2 Print API + Java Print Service.
Java 2 Print API is something like 1990 style. To avoid to create your code using Java 2 Print API you could use PDFBox http://pdfbox.apache.org as a framework.
With PDFBox you could create a PDF document (http://pdfbox.apache.org/1.8/cookbook/documentcreation.html) but instead of save, print it using that code:
PrinterJob printJob = PrinterJob.getPrinterJob();
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
printJob.setPrintService(service);
document.silentPrint(printJob);
It works fine in my Mac.
I have a question in Java how can I check if an image http path is valid or existing?
For example:
This image is existing.
http://g0.gstatic.com/ig/images/promos/homepage_home.png
But this one is not.
http://sampledomain.com/images/fake.png
I would like to make a logic such that:
If(image is existing)
- do this
Else
- do others
Thanks
UPDATE:
Tried it with this code that I got while googling:
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
public class TestImage {
public static void main(String[] arg){
Image image = null;
try {
URL url = new URL("http://g0.gstatic.com/ig/images/promos/homepage_home.png");
image = ImageIO.read(url);
} catch (IOException e) {
System.out.println("Error");
}
}
}
But I always get an error...I am not sure if this is possible.. Any other thoughts?
Make an Http Head request. If it's an existing path you'll get a response back, otherwise you'll get an error.
This does not check that it is a valid image though, just that the path exists. If you want to check whether the image is valid, I think you have got no choice other than to download it.
You can check if the image exists or not using selenium javascript executor.
Hope this code helps you -
picPath is the Url path you want to validate.
result = (Boolean) ((JavascriptExecutor) driver).executeScript(
"var http = new XMLHttpRequest(); http.open('HEAD',arguments[0], false); http.send();return http.status!=404;", picPath);