文章目錄
1、Java的打印簡介
在咱們的實際工做中,常常須要實現打印功能。但因爲歷史緣由,Java 提供的打印功能一直都比較弱。實際上最初的 jdk 根本不支持打印,直到 jdk1.1 才引入了很輕量的打印支持。實際上,SUN 公司也一直致力於 Java 打印功能的完善,而 Java2 平臺則終於有了一個健壯的打印模式的開端, jdk1.4 則提供了一套完整的"Java 打印服務 API" (Java Print Service API),它對已有的打印功能是積極的補充。java
本次調研的打印對象主要是JPG,PDF和Word這三種常見文件格式。apache
2、Java打印實現
2.1 JPG圖片文件格式打印實現
打印JPG圖片格式的文件,本次採用的Java原生的打印方式。app
jdk1.4以後對打印功能有了很好的支持。Java 的打印 API 主要存在於 java.awt.print 包中。而 jdk1.4 新增的類則主要存在於 javax.print 包及其相應的子包 javax.print.event 和 javax.print.attribute 中。其中 javax.print 包中主要包含打印服務的相關類,而 javax.print.event 則包含打印事件的相關定義,javax.print.attribute 則包括打印服務的可用屬性列表等。能夠很好的解決打印JPG圖片格式的需求。maven
優勢:jdk的原生支持的打印功能,可直接使用,支持設置各項打印參數。ide
缺點:侷限性較大,只能打印一些圖片和文本格式的文件。工具
具體實現以下:ui
public static void main(String[] argv) throws Exception { File file = new File("E:\\a.jpg"); String printerName = "HP MFP M436 PCL6";//打印機名包含字串 PDFPrint(file,printerName); } // 傳入文件和打印機名稱 public static void JPGPrint(File file,String printerName) throws PrintException { if (file == null) { System.err.println("缺乏打印文件"); } InputStream fis = null; try { // 設置打印格式,若是未肯定類型,可選擇autosense DocFlavor flavor = DocFlavor.INPUT_STREAM.JPEG; // 設置打印參數 PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); aset.add(new Copies(1)); //份數 //aset.add(MediaSize.ISO.A4); //紙張 // aset.add(Finishings.STAPLE);//裝訂 aset.add(Sides.DUPLEX);//單雙面 // 定位打印服務 PrintService printService = null; if (printerName != null) { //得到本臺電腦鏈接的全部打印機 PrintService[] printServices = PrinterJob.lookupPrintServices(); if(printServices == null || printServices.length == 0) { System.out.print("打印失敗,未找到可用打印機,請檢查。"); return ; } //匹配指定打印機 for (int i = 0;i < printServices.length; i++) { System.out.println(printServices[i].getName()); if (printServices[i].getName().contains(printerName)) { printService = printServices[i]; break; } } if(printService==null){ System.out.print("打印失敗,未找到名稱爲" + printerName + "的打印機,請檢查。"); return ; } } fis = new FileInputStream(file); // 構造待打印的文件流 Doc doc = new SimpleDoc(fis, flavor, null); DocPrintJob job = printService.createPrintJob(); // 建立打印做業 job.print(doc, aset); } catch (FileNotFoundException e1) { e1.printStackTrace(); } finally { // 關閉打印的文件流 if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
2.2 PDF文件格式打印實現
在通過網上的查找及對比,我選擇了使用Apache PDFbox來實現進行PDF文件格式的打印。spa
Apache PDFbox是一個開源的、基於Java的、支持PDF文檔生成的工具庫,它能夠用於建立新的PDF文檔,修改現有的PDF文檔,還能夠從PDF文檔中提取所需的內容。Apache PDFBox還包含了數個命令行工具。在此,咱們只研究打印功能。.net
優勢:功能強大,開源軟件,較完美的解決了PDF格式文件的一系列處理,使用方便。插件
缺點:
具體實現以下:
①直接導入maven依賴:
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.6</version> </dependency>
②代碼調用實現
public static void main(String[] args) throws Exception { String pdfFile = "E:\\a.pdf";//文件路徑 File file = new File(pdfFile); String printerName = "HP MFP M436 PCL6";//打印機名包含字串 print(file,printerName); } public static void PDFprint(File file ,String printerName) throws Exception { PDDocument document = null; try { document = PDDocument.load(file); PrinterJob printJob = PrinterJob.getPrinterJob(); printJob.setJobName(file.getName()); if (printerName != null) { // 查找並設置打印機 //得到本臺電腦鏈接的全部打印機 PrintService[] printServices = PrinterJob.lookupPrintServices(); if(printServices == null || printServices.length == 0) { System.out.print("打印失敗,未找到可用打印機,請檢查。"); return ; } PrintService printService = null; //匹配指定打印機 for (int i = 0;i < printServices.length; i++) { System.out.println(printServices[i].getName()); if (printServices[i].getName().contains(printerName)) { printService = printServices[i]; break; } } if(printService!=null){ printJob.setPrintService(printService); }else{ System.out.print("打印失敗,未找到名稱爲" + printerName + "的打印機,請檢查。"); return ; } } //設置紙張及縮放 PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.ACTUAL_SIZE); //設置多頁打印 Book book = new Book(); PageFormat pageFormat = new PageFormat(); //設置打印方向 pageFormat.setOrientation(PageFormat.PORTRAIT);//縱向 pageFormat.setPaper(getPaper());//設置紙張 book.append(pdfPrintable, pageFormat, document.getNumberOfPages()); printJob.setPageable(book); printJob.setCopies(1);//設置打印份數 //添加打印屬性 HashPrintRequestAttributeSet pars = new HashPrintRequestAttributeSet(); pars.add(Sides.DUPLEX); //設置單雙頁 printJob.print(pars); }finally { if (document != null) { try { document.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static Paper getPaper() { Paper paper = new Paper(); // 默認爲A4紙張,對應像素寬和高分別爲 595, 842 int width = 595; int height = 842; // 設置邊距,單位是像素,10mm邊距,對應 28px int marginLeft = 10; int marginRight = 0; int marginTop = 10; int marginBottom = 0; paper.setSize(width, height); // 下面一行代碼,解決了打印內容爲空的問題 paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom)); return paper; }
2.3 Word文件格式打印實現
打印word這裏共使用了2種方法,一種是直接使用jacob進行打印,這種方法打印word我暫時沒有找到設置打印參數的相關方式,(可是打印Excle好像設置打印參數沒問題,在PrintOut操做裏設置,參數具體可參考https://msdn.microsoft.com/zh-cn/vba/excel-vba/articles/worksheets-printout-method-excel),第二種是將word先轉成pdf文件,而後進行打印。
2.3.1 Word文件採用jacob插件進行打印實現。
Jacob是一個 Java到微軟的com接口的橋樑。使用Jacob容許任何JVM訪問com對象,從而使Java應用程序可以調用com對象。若是你要對 Word、Excel 進行處理,Jacob是一個好的選擇。
優勢:能夠很好的處理word文檔的相關操做。
缺點:必須手動引入dll文件,暫時未找到方法設置打印相關參數,只能暫時實現靜默打印,還需安裝office2003以上版本(lz是office365,未激活也可)。
具體實現以下:
①下載jacob.zip ,對應(86/64)的dll文件放在%Java_Home%jre/bin目錄下。
下載地址:https://sourceforge.net/projects/jacob-project/
②導入jacob.jar到工程中
在工程中建立lib文件夾保存jacob.jar:reseources—lib—jacob.jar
添加Maven依賴:
<!--添加本地的jacob.jar包--> <!--添加本地的jacob.jar包--> <dependency> <groupId>com.jacob</groupId> <artifactId>jacob</artifactId> <version>1.19</version> <scope>system</scope> <systemPath>${basedir}/src/main/resources/lib/jacob.jar</systemPath> </dependency>
具體代碼實現:
public static void main(String[] args) { String filePath = "E:\\a.docx";//文件路徑 String printerName = "HP MFP M436 PCL6";//打印機名包含字串 printWord(filePath,printerName); } public static void printWord(String filePath, String printerName){ // 初始化線程 ComThread.InitSTA(); ActiveXComponent word = new ActiveXComponent("Word.Application"); //設置打印機名稱 word.setProperty("ActivePrinter", new Variant(printerName)); // 這裏Visible是控制文檔打開後是可見仍是不可見,如果靜默打印,那麼第三個參數就設爲false就行了 Dispatch.put(word, "Visible", new Variant(false)); // 獲取文檔屬性 Dispatch document = word.getProperty("Documents").toDispatch(); // 打開激活文擋 Dispatch doc=Dispatch.call(document, "Open", filePath).toDispatch(); //Dispatch doc = Dispatch.invoke(document, "Open", Dispatch.Method, // new Object[] { filePath }, new int[1]).toDispatch(); try{ Dispatch.callN(doc, "PrintOut"); System.out.println("打印成功!"); }catch (Exception e){ e.printStackTrace(); System.out.println("打印失敗"); }finally { try { if (doc != null) { Dispatch.call(doc, "Close", new Variant(0));//word文檔關閉 } } catch (Exception e2) { e2.printStackTrace(); } //退出 word.invoke("Quit", new Variant[0]); //釋放資源 ComThread.Release(); ComThread.quitMainSTA(); } }
2.3.2 先將word轉化爲pdf文件,而後打印pdf(lz使用)
優勢:可設置打印參數等操做
缺點:也要引入jacob相關依賴和文件
具體實現步驟以下:
①由於轉化也是使用jacob插件,因此也須要根據第一種方法同樣引入jacob相關依賴和文件
②打印pdf文件時,使用的是上面講述的pdfbox插件,因此也須要引入pdfbox的依賴
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.6</version> </dependency>
③代碼具體實現
首先將word文件轉化爲pdf文件
//word轉化pdf,傳入轉換前的文件路徑(例:"E:\\a.docx")和轉換後的文件路徑(例:"E:\\a.pdf") public static void wordToPDF(String sFilePath,String toFilePath) { System.out.println("啓動 Word..."); long start = System.currentTimeMillis(); ActiveXComponent app = null; Dispatch doc = null; try { app = new ActiveXComponent("Word.Application"); app.setProperty("Visible", new Variant(false)); Dispatch docs = app.getProperty("Documents").toDispatch(); doc = Dispatch.call(docs, "Open", sfilePath).toDispatch(); System.out.println("打開文檔:" + sfilePath); System.out.println("轉換文檔到 PDF:" + toFilePath); File tofile = new File(toFilePath); if (tofile.exists()) { tofile.delete(); } Dispatch.call(doc, "SaveAs", toFilePath, // FileName 17);//17是pdf格式 long end = System.currentTimeMillis(); System.out.println("轉換完成..用時:" + (end - start) + "ms."); } catch (Exception e) { System.out.println("========Error:文檔轉換失敗:" + e.getMessage()); } finally { Dispatch.call(doc, "Close", false); System.out.println("關閉文檔"); if (app != null) app.invoke("Quit", new Variant[]{}); } // 若是沒有這句話,winword.exe進程將不會關閉 ComThread.Release(); }
而後打印pdf文件(這裏傳入的文件爲上面word轉化生成的pdf文件)
//這裏傳入的文件爲word轉化生成的pdf文件 public static void PDFprint(File file ,String printerName) throws Exception { PDDocument document = null; try { document = PDDocument.load(file); PrinterJob printJob = PrinterJob.getPrinterJob(); printJob.setJobName(file.getName()); if (printerName != null) { // 查找並設置打印機 //得到本臺電腦鏈接的全部打印機 PrintService[] printServices = PrinterJob.lookupPrintServices(); if(printServices == null || printServices.length == 0) { System.out.print("打印失敗,未找到可用打印機,請檢查。"); return ; } PrintService printService = null; //匹配指定打印機 for (int i = 0;i < printServices.length; i++) { System.out.println(printServices[i].getName()); if (printServices[i].getName().contains(printerName)) { printService = printServices[i]; break; } } if(printService!=null){ printJob.setPrintService(printService); }else{ System.out.print("打印失敗,未找到名稱爲" + printerName + "的打印機,請檢查。"); return ; } } //設置紙張及縮放 PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.ACTUAL_SIZE); //設置多頁打印 Book book = new Book(); PageFormat pageFormat = new PageFormat(); //設置打印方向 pageFormat.setOrientation(PageFormat.PORTRAIT);//縱向 pageFormat.setPaper(getPaper());//設置紙張 book.append(pdfPrintable, pageFormat, document.getNumberOfPages()); printJob.setPageable(book); printJob.setCopies(1);//設置打印份數 //添加打印屬性 HashPrintRequestAttributeSet pars = new HashPrintRequestAttributeSet(); pars.add(Sides.DUPLEX); //設置單雙頁 printJob.print(pars); }finally { if (document != null) { try { document.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static Paper getPaper() { Paper paper = new Paper(); // 默認爲A4紙張,對應像素寬和高分別爲 595, 842 int width = 595; int height = 842; // 設置邊距,單位是像素,10mm邊距,對應 28px int marginLeft = 10; int marginRight = 0; int marginTop = 10; int marginBottom = 0; paper.setSize(width, height); // 下面一行代碼,解決了打印內容爲空的問題 paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom)); return paper; }
最後別忘了將生成的pdf文件刪除
File file=new File(toFilePath); if(file.exists()&&file.isFile()) file.delete();
3、總結
至此,本次實現的JPG、PDF和Word三種文件格式的打印已經所有實現,分別採用了原生打印和PDFbox插件和jacob插件進行實現。記錄一下,以防忘記,留待後續使用。