我有一个需求需要以两种不同的方式打印PDF文件——一种是通过网页进行打印预览,用户可以选择打印机并打印;第二种方式是自动化打印,只需点击按钮,PDF文件就应该被发送到打印机。
通过网页的第一种打印方式运行良好,但第二种方式没有成功。成功检索了默认打印机以进行自动打印,但并未打印,并且也没有错误信息。以下是我的分析:
- 最初,我认为
DocFlavor
不受支持。然后我列出了该打印机支持的DocFlavor
列表,其中之一是application/octet-stream,即DocFlavor.INPUT_STREAM.AUTOSENSE
。因此,该格式受打印机支持。 - 然后,我添加了
PrintJobListener
来检查打印作业是否失败。当我将该侦听器添加到打印作业时,它会打印出No_More_Events
和DATA_TRANSFER_COMPLETE
,如果作业成功,则应该打印出JOB_COMPLETE
。 - 最后一步是调试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。但都无法使用,而且会出现运行时错误,提示不支持该格式。