Java中的自动打印功能无法正常工作

12

我有一个需求需要以两种不同的方式打印PDF文件——一种是通过网页进行打印预览,用户可以选择打印机并打印;第二种方式是自动化打印,只需点击按钮,PDF文件就应该被发送到打印机。

通过网页的第一种打印方式运行良好,但第二种方式没有成功。成功检索了默认打印机以进行自动打印,但并未打印,并且也没有错误信息。以下是我的分析:

  1. 最初,我认为DocFlavor不受支持。然后我列出了该打印机支持的DocFlavor列表,其中之一是application/octet-stream,即DocFlavor.INPUT_STREAM.AUTOSENSE。因此,该格式受打印机支持。
  2. 然后,我添加了PrintJobListener来检查打印作业是否失败。当我将该侦听器添加到打印作业时,它会打印出No_More_EventsDATA_TRANSFER_COMPLETE,如果作业成功,则应该打印出JOB_COMPLETE
  3. 最后一步是调试Java代码。当我执行job.print()时,它进入Win32PrintJob.print()方法。我按F6逐行执行以查看它在做什么。我将其与GrepCode中的代码进行了比较,因为源代码未加载到eclipse中。一切都进行得很好,我没有看到任何错误。唯一一个它没有进入的地方是检查mDestination值的这个块,因为我没有提供它,所以它没有继续执行。

请参阅下面的代码:

if (mDestination != null) { // if destination attribute is set
    try {
        FileOutputStream fos = new FileOutputStream(mDestination);
        byte [] buffer = new byte[1024];
        int cread;

        while ((cread = instream.read(buffer, 0, buffer.length)) >= 0) {
            fos.write(buffer, 0, cread);
        }
        fos.flush();
        fos.close();
    } catch (FileNotFoundException fnfe) {
        notifyEvent(PrintJobEvent.JOB_FAILED);
        throw new PrintException(fnfe.toString());
    } catch (IOException ioe) {
        notifyEvent(PrintJobEvent.JOB_FAILED);
        throw new PrintException(ioe.toString());
    }
    notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
    notifyEvent(PrintJobEvent.JOB_COMPLETE);
    service.wakeNotifier();
    return;
}

这是唯一一个提到JOB_COMPLETE的地方。我认为这个代码块是用来写入文件的,而对我来说是不必要的。

我认为实际的打印操作发生在同一个方法Win32PrintJob.print()中的下一行。

private native boolean More ...printRawData(byte[] data, int count);

但是这个方法是本地方法,所以我不知道里面发生了什么。

请让我知道为什么我不能打印PDF。

编辑:

附上打印文件的代码:

PrintService pss = PrintServiceLookup.lookupDefaultPrintService();
DocPrintJob job = pss.createPrintJob();
DocAttributeSet das = new HashDocAttributeSet();
Doc document;
try {
    document = new SimpleDoc(new FileInputStream(new File(fileName)), DocFlavor.INPUT_STREAM.AUTOSENSE, das);

    PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
    job.addPrintJobListener(new PrintJobWatcher());
    job.print(document, pras);
}

注意:我尝试了不同的格式,如PDF、PCL。但都无法使用,而且会出现运行时错误,提示不支持该格式。


请问您能否更新一下您的问题,附上用于打印文件的代码?正如您之前所提到的,该代码是用于写入文件的。 - Parth Soni
我认为问题在于您需要先渲染PDF,而不能直接打印。大约10年前,我使用Acrobat CLI静默打印功能解决了此问题...但现在可能有其他替代方法。 - maraca
@maraca:我可以在Xerox打印机上打印它,但无法在富士打印机上打印。 - Anand
你尝试过将PrintRequestAttributeSet和DocAttributeSet都传递为null吗? - Lorenzo Sciuto
@LorenzoSciuto:是的,我发送了NULL。仍然没有运气。 - Anand
2个回答

1
我最近也有同样的任务,对于第二个打印选项的答案并不那么直接(也尝试过JPedal,Samba和其他解决方案..)。最简单的打印方式(我最终尝试)是将文件放置在打印队列中,即根位置。例如:MY_SERVER \ PRINTER_NAME \
现在问题变成了环境/操作系统问题,而不是Java问题。通过安装在Windows机器上的应用程序,您可能可以访问该文件夹,复制要打印的文件,然后就可以打印了。此外,使用您使用的方法,您还可以为打印作业命名、指定打印份数等。
然而,一旦应用程序安装在服务器上,情况就完全不同了,特别是如果您正在使用Linux服务器。首先,您必须将Windows地址转换为Linux地址,才能尝试复制文件/打印它。
其次,这是关键的一点,如果文件不是更复杂/专有数据流的一部分,打印机很少/难以只是“接受文件”进行打印。例如,您可以找出打印机与服务器或甚至在按“Ctrl+P”时与您的计算机通信的“通信语言”,这将主要是.xml文件或其他格式。
为了“弄清”这种格式,您需要开发一个应用程序(最终使用Java),该应用程序将调用打印机。当然,您也可以尝试在该服务器上安装Cups4j或设置打印机服务器(假设您工作的地方没有这样的设置),但是当打印机更改、添加到网络等时,这将会引起问题。最终,您可以坚持“Ctrl+P”的方法,制作一个调用浏览器中的“CTRL+P”的小JS脚本,或者重新创建轮子,这并不是一件坏事(因为也有人选择这种方法...但我没有找到任何示例),但可能需要比您拥有的时间更长。希望我以某种方式帮助了您(对于冗长的帖子感到抱歉..但这是我搜索和研究了相当长时间的主题)。

0

你尝试过使用JPadel打印PDF文件吗:

摘自示例代码

final PdfBook pdfBook = new PdfBook(pdfDecoder, printJob.getPrintService(), attributes);
pdfBook.setChooseSourceByPdfPageSize(false);

final SimpleDoc doc = new SimpleDoc(pdfBook, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);

// used to track print activity
printJob.addPrintJobListener(new PDFPrintJobListener());

try {
    printJob.print(doc, attributes);
}
catch (final Exception e) {
    LogWriter.writeLog("Exception " + e + " printing");
    // <end-demo>
}

此外,您可以提供打印机名称并添加一个名为PDFPrintJobListener的监听器。

我可以在施乐打印机上无问题地打印PDF。但是在客户处的其他打印机上遇到了问题。 - Anand
@Anand...你的意思是说你的自动打印功能可以与施乐打印机配合使用,但不能与富士类型的打印机配合使用。 - Garry
是的,这种富士打印机不会自动打印。 - Anand

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