Java实现未配置网络打印机直接打印及服务查找空值问题
Hey, let's break down what's going wrong here and fix it. The core issue with your code is that you're grabbing the default system print service (which is a printer already configured locally) and then trying to force it to use an unconfigured IPP printer via the PrinterName attribute—this won't work because the default service has no idea how to communicate with that external printer. PrinterServiceLookup returns null for it because the printer isn't registered in your OS's print queue.
Here are a few solid solutions depending on your Java version:
1. Use Java 11+'s Built-in IPP Client API (Recommended)
Starting with Java 11, the JDK includes native support for the Internet Printing Protocol (IPP), so you can connect directly to the printer's URI without OS-level configuration.
Updated Code:
import javax.print.*; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.standard.Copies; import java.io.InputStream; public int printDoc(InputStream is) throws PrintException { String printerUri = "ipp://blrprt01.blr.network18.com/23Flr_Printer1"; // Set up print attributes PrintRequestAttributeSet printAttribs = new HashPrintRequestAttributeSet(); printAttribs.add(new Copies(1)); // Look up print services that support our document flavor and attributes PrintService[] availableServices = PrintServiceLookup.lookupPrintServices( DocFlavor.INPUT_STREAM.AUTOSENSE, printAttribs ); // Find the service matching our IPP URI PrintService targetPrinter = null; for (PrintService service : availableServices) { if (service.getName().contains(printerUri)) { targetPrinter = service; break; } } // Fallback: Try directly adding the printer URI to attributes if not found if (targetPrinter == null) { try { javax.print.attribute.standard.PrinterName printerName = new javax.print.attribute.standard.PrinterName(printerUri, null); printAttribs.add(printerName); availableServices = PrintServiceLookup.lookupPrintServices(null, printAttribs); targetPrinter = availableServices.length > 0 ? availableServices[0] : null; } catch (Exception e) { e.printStackTrace(); } } if (targetPrinter == null) { throw new PrintException("Failed to connect to the specified IPP printer. Check URI and network access."); } // Set up print job and listener DocPrintJob printJob = targetPrinter.createPrintJob(); printJob.addPrintJobListener(new PrintJobAdapter() { @Override public void printDataTransferCompleted(PrintJobEvent event) { System.out.println("transfer complete"); } @Override public void printJobNoMoreEvents(PrintJobEvent event) { System.out.println("received no more events"); } }); // Print the document Doc doc = new SimpleDoc(is, DocFlavor.INPUT_STREAM.AUTOSENSE, null); printJob.print(doc, printAttribs); return 0; }
2. Third-Party IPP Library (For Java 8 or Older)
If you're stuck on Java 8 or earlier, the JDK doesn't have native IPP support, so use a lightweight third-party library like ipp-client.
Step 1: Add Maven Dependency
<dependency> <groupId>com.github.jochenberger</groupId> <artifactId>ipp-client</artifactId> <version>0.5.0</version> </dependency>
Step 2: Example Code
import de.odysseus.ipp.client.IppClient; import de.odysseus.ipp.client.IppJob; import de.odysseus.ipp.client.IppPrinter; import java.io.InputStream; import java.net.URI; public int printDoc(InputStream is) throws Exception { URI printerUri = URI.create("ipp://blrprt01.blr.network18.com/23Flr_Printer1"); // Connect to the printer and send the job try (IppClient client = new IppClient()) { IppPrinter printer = client.getPrinter(printerUri); IppJob job = printer.createJob(); job.setCopies(1); // Adjust the MIME type to match your document (e.g., image/jpeg for JPEGs) job.print(is, "application/octet-stream"); // Optional: Wait for the job to finish job.waitForTermination(); } return 0; }
3. Critical Pre-Checks
Before testing, make sure these are in place:
- Your application server can reach the printer's IPP port (default 631)—no firewalls or network rules blocking traffic.
- The IPP URI is correct: Test it by visiting
http://blrprt01.blr.network18.com:631/printers/23Flr_Printer1in a browser (you should see the printer's management page). - If the printer requires authentication, add credentials to your attributes (e.g.,
printAttribs.add(new RequestingUserName("your-username"))) or configure the IPP client with auth details.
内容的提问来源于stack exchange,提问作者Pandey Amit

