如何使用Java在网络打印机上打印?

10

使用Java,我需要将内容打印到网络打印机上,但该打印机未在本地安装。我只知道打印机名称。所有我看到的教程都是从以下代码开始:

PrintService []services = PrinterJob.lookupPrintServices();

问题在于可能没有安装任何打印机,因此在这种情况下服务将为空。我需要直接设置打印机名称,而不仅仅是枚举可见打印机。


通过'lookupPrintServices()'可用的打印机列出了操作系统和运行应用程序的用户注册的打印机。例如,在Windows中,您需要确保所需的打印机已注册为应用程序正在运行的任何活动目录用户(本地用户、注册服务等)。这是一次性注册。在网络上,您还可以将打印机注册到网络并访问它//server/printername。 - JoshDM
我不需要使用lookupPrintServices()。我有打印机名称以//server/printername格式。问题是,lookupPrintServices无法看到它们中的任何一个,因此我无法注册或安装它。在.NET中,您可以在printersettings对象中简单地设置打印机名称。我想知道,在Java中是否存在类似的可能性。很简单。我有PDF文件(处理PDFBox)和打印机名称,我想在不打开Acrobat的情况下静默打印它。我想知道最简单的方法。 - user1431544
1
即使打印机已经注册到网络,如果在运行Java应用程序的域用户的Windows控制面板中看不到该打印机,则Java通过awt打印API也无法看到它。你可能拥有正确的名称和路径,但如果它没有注册到应用程序所在的服务器上,它将无法被找到。 - JoshDM
2个回答

12

如果 Java AWT Printing 在运行打印应用程序的 Windows / Active Directory 用户中没有注册打印机路径,那么它将无法通过路径找到打印机。您必须通过 Windows“设备和打印机”将打印机路径注册为该用户的打印机才能使其可见。然后,作为该用户,您必须运行 lookupPrintServices 查看可用的打印机列表,并通过确切的名称 String 检索正确的 PrintService

/**
 * Retrieve the specified Print Service; will return null if not found.
 * @return
 */
public static PrintService findPrintService(String printerName) {

    PrintService service = null;
    
    // Get array of all print services - sort order NOT GUARANTEED!
    PrintService[] services = PrinterJob.lookupPrintServices();
    
    // Retrieve specified print service from the array
    for (int index = 0; service == null && index < services.length; index++) {
        
        if (services[index].getName().equalsIgnoreCase(printerName)) {

            service = services[index];
        }
    }

    // Return the print service
    return service;
}

/**
 * Retrieve a PrinterJob instance set with the PrinterService using the printerName.
 * 
 * @return
 * @throws Exception IllegalStateException if expected printer is not found.
 */
public static PrinterJob findPrinterJob(String printerName) throws Exception {

    // Retrieve the Printer Service
    PrintService printService = PrintUtility.findPrintService(printerName);

    // Validate the Printer Service
    if (printService == null) {

        throw new IllegalStateException("Unrecognized Printer Service \"" + printerName + '"');
    }
    
    // Obtain a Printer Job instance.
    PrinterJob printerJob = PrinterJob.getPrinterJob();
    
    // Set the Print Service.
    printerJob.setPrintService(printService);

    // Return Print Job
    return printerJob;
}

/**
 * Printer list does not necessarily refresh if you change the list of 
 * printers within the O/S; you can run this to refresh if necessary.
 */
public static void refreshSystemPrinterList() {

    Class[] classes = PrintServiceLookup.class.getDeclaredClasses();

    for (int i = 0; i < classes.length; i++) {

        if ("javax.print.PrintServiceLookup$Services".equals(classes[i].getName())) {

            sun.awt.AppContext.getAppContext().remove(classes[i]);
            break;
        }
    }
}

1
所以你是想告诉我,没有办法在未注册的打印机上打印?太好了。谢谢。 - user1431544
老实说,我不知道。这是客户的网络,他有自己的原因。我知道这很糟糕,但注册打印机不是一个选项。 - user1431544
他只知道他的老系统可以处理这个问题:) 我可以用ComponentOne在.NET中打印(应用程序是用它编写的)。问题是,这种类型的打印需要很长时间(几分钟)。当打印机注册后,它可以在几秒钟内打印完成(使用同一台物理打印机)。所以我想尝试另一个组件,并发现存在PDFBox,它可以打印pdf,但最初是用Java编写的。现在,我正在使用IKVM,并试图找出如何创建PrintJob,PDFBox的打印方法将其作为参数。 - user1431544
lookupPrintServices不能保证返回任何顺序或大小,因为在任何给定时间可用于Windows用户的值可能会有所不同;您需要自行对它们进行排序。 AppContextsun.awt.AppContext - JoshDM
1
未注册的打印机通常可以通过端口9100上的套接字直接写入。这需要您了解打印机期望的低级数据。许多办公室打印机可以本地处理PDF(请确保大小正确,PDFBOX使用驱动程序处理大小,您正在绕过使用未注册的打印机)。 - tresf
显示剩余4条评论

2

在我的情况下,出现了身份验证错误,因为我使用本地用户帐户搜索打印机,所以找不到共享打印机。使用其他帐户或更改打印机授权后,我可以找到它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接