功能描述:
在二手車項目中需要實現一個自動打印的功能。將打印的設置在java代碼中寫好,直接調用打印機打印,不需要有打印設置的頁面。這裏我使用的是Java自帶的方式,一開始是打印pdf,但是由於公司的打印機不能識別application/pdf類型,因此最後我打印的是pdf轉換的jpg圖片。
(說明:最後我寫的功能正常執行並打印出圖片,但是由於該項目是SaaS軟件,服務器由公司維護,而該代碼執行的環境是需要運行程序的服務器與打印機在同一個局域網,這樣才能正常識別,所以沒有使用。爲防止你走彎路,參考我的代碼之前最好問清楚服務器是在哪兒維護)
代碼如下:
1.獲取輸入流(這裏是通過我們公司的pdf服務器的路徑獲得的)
@RequestMapping(value = "/printTransferPdf" ,method = RequestMethod.POST) @ApiOperation(value = "打印過戶單據pdf", notes = "打印過戶單據pdf" ,tags = {"web"}) public AbstractOutputDto downloadTransferPdf(@RequestBody PrintTransferOps ops )throws Exception{ PdfOutput output=transferService.createTransferPDF(ops); URL url=new URL(output.getPicPath()); URLConnection conn = url.openConnection(); InputStream is = conn.getInputStream(); System.out.println(output.getPicPath()); AbstractOutputDto abstractOutputDto= transferService.printPDF(is); return abstractOutputDto; }
2.打印功能
public AbstractOutputDto printPDF(InputStream in) throws IOException { AbstractOutputDto abstractOutputDto = new AbstractOutputDto(); //1.得到一個文件的輸入流 BufferedInputStream fiStream = new BufferedInputStream(in); //這是要打印文件的格式,如果是PDF文檔要設爲自動識別 DocFlavor fileFormat = DocFlavor.INPUT_STREAM.JPEG; DocAttributeSet das=new HashDocAttributeSet(); das.add(OrientationRequested.PORTRAIT); //2.得到要打印的文檔類DOC Doc myDoc = new SimpleDoc(fiStream, fileFormat, das); //3.生成一個打印屬性設置對象 PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); /*aset.add(new Copies(1));//Copies-打印份數1份 aset.add(MediaSizeName.ISO_A4);//A4紙張 aset.add(Sides.ONE_SIDED);//雙面打印*/ //4.關鍵一步,得到當前機器上所有已經安裝的打印機 //傳入的參數是文檔格式跟打印屬性,只有支持這個格式與屬性的打印機纔會被找到 PrintService printService=PrintServiceLookup.lookupDefaultPrintService(); if (printService!= null) { DocFlavor[] flavors=printService.getSupportedDocFlavors(); for (int i = 0; i < flavors.length; i++) { System.out.println("\t" + flavors[i]); } //5.用打印服務生成一個文檔打印任務,這裏用的是第一個服務 //也可以進行篩選,services[i].getName()可以得到打印機名稱,可用名稱進行比較得到自己想要的打印機 DocPrintJob job=printService.createPrintJob(); job.addPrintJobListener(new PrintJobListener() { @Override public void printJobRequiresAttention(PrintJobEvent arg0) { System.out.println("printJobRequiresAttention"); } @Override public void printJobNoMoreEvents(PrintJobEvent arg0) { System.out.println("通知客戶端,不需要再提供事件"); } @Override public void printJobFailed(PrintJobEvent arg0) { System.out.println("通知客戶端無法完成作業,必須重新提交"); } @Override public void printJobCompleted(PrintJobEvent arg0) { System.out.println("打印結束"); } @Override public void printJobCanceled(PrintJobEvent arg0) { System.out.println("作業已被用戶或者程序取消"); } @Override public void printDataTransferCompleted(PrintJobEvent arg0) { System.out.println("數據已成功傳輸打印機"); } }); try { //6.最後一步,執行打印文檔任務,傳入的參數是Doc文檔類,與屬性 job.print(myDoc, aset);//成功後電腦會提示已有文檔添加到打印隊列 abstractOutputDto.setStatus(1); abstractOutputDto.setMsg("打印任務已添加"); } catch (PrintException pe) { pe.printStackTrace(); } } else { abstractOutputDto.setStatus(0); abstractOutputDto.setMsg("打印機未連接"); } return abstractOutputDto; }
注意:
我在寫的時候遇到了幾個問題:
1.PrintServiceLookup.lookupPrintServices()方法識別的打印機是需要符合它的文檔格式和打印屬性的。可能導致獲取不到PrintService。最後我使用lookupDefaultPrintService方法獲取的默認打印機,這需要本地設置一下。
2.打印文件的格式最好設具體值,設置爲自動識別的話可能會出問題,導致傳輸的數據不被打印機處理
3.printService.getSupportedDocFlavors方法可以遍歷出該打印機支持的文件格式
4.給文檔打印任務添加監聽可以幫助查看哪一步出現了問題。我傳入pdf數據的時候就是打印機明明獲取了卻不處理,也不報錯,鬧心。