JAVA調用打印機

一、Java的打印簡介

在我們的實際工作中,經常需要實現打印功能。但由於歷史原因,Java 提供的打印功能一直都比較弱。實際上最初的 jdk 根本不支持打印,直到 jdk1.1 才引入了很輕量的打印支持。實際上,SUN 公司也一直致力於 Java 打印功能的完善,而 Java2 平臺則終於有了一個健壯的打印模式的開端, jdk1.4 則提供了一套完整的"Java 打印服務 API" (Java Print Service API),它對已有的打印功能是積極的補充。

本次調研的打印對象主要是JPG,PDF和Word這三種常見文件格式。

二、Java打印實現

2.1 JPG圖片文件格式打印實現

打印JPG圖片格式的文件,本次採用的Java原生的打印方式。

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圖片格式的需求。

優點:jdk的原生支持的打印功能,可直接使用,支持設置各項打印參數。

缺點:侷限性較大,只能打印一些圖片和文本格式的文件。

  1. public static void main(String[] argv) throws Exception {
  2.         File file = new File("E:\\a.jpg");
  3.         String printerName = "HP MFP M436 PCL6";//打印機名包含字串
  4.         PDFPrint(file,printerName);
  5.     }
  6. // 傳入文件和打印機名稱
  7. public static void JPGPrint(File file,String printerName) throws PrintException {
  8.     if (file == null) {
  9.         System.err.println("缺少打印文件");
  10.     }
  11.     InputStream fis = null;
  12.     try {
  13.         // 設置打印格式,如果未確定類型,可選擇autosense
  14.         DocFlavor flavor = DocFlavor.INPUT_STREAM.JPEG;
  15.         // 設置打印參數
  16.         PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
  17.         aset.add(new Copies(1)); //份數
  18.         //aset.add(MediaSize.ISO.A4); //紙張
  19.         // aset.add(Finishings.STAPLE);//裝訂
  20.         aset.add(Sides.DUPLEX);//單雙面
  21.         // 定位打印服務
  22.         PrintService printService = null;
  23.         if (printerName != null) {
  24.             //獲得本臺電腦連接的所有打印機
  25.             PrintService[] printServices = PrinterJob.lookupPrintServices();
  26.             if(printServices == null || printServices.length == 0) {
  27.                 System.out.print("打印失敗,未找到可用打印機,請檢查。");
  28.                 return ;
  29.             }
  30.             //匹配指定打印機
  31.             for (int i = 0;i < printServices.length; i++) {
  32.                 System.out.println(printServices[i].getName());
  33.                 if (printServices[i].getName().contains(printerName)) {
  34.                     printService = printServices[i];
  35.                     break;
  36.                 }
  37.             }
  38.             if(printService==null){
  39.                 System.out.print("打印失敗,未找到名稱爲" + printerName + "的打印機,請檢查。");
  40.                 return ;
  41.             }
  42.         }
  43.         fis = new FileInputStream(file); // 構造待打印的文件流
  44.         Doc doc = new SimpleDoc(fis, flavor, null);
  45.         DocPrintJob job = printService.createPrintJob(); // 創建打印作業
  46.         job.print(doc, aset);
  47.     } catch (FileNotFoundException e1) {
  48.         e1.printStackTrace();
  49.     } finally {
  50.  // 關閉打印的文件流
  51.         if (fis != null) {
  52.             try {
  53.                 fis.close();
  54.             } catch (IOException e) {
  55.                 e.printStackTrace();
  56.             }
  57.         }
  58.     }
  59. }
  60. }
     

 

2.2 PDF文件格式打印實現

在經過網上的查找及對比,我選擇了使用Apache PDFbox來實現進行PDF文件格式的打印。

Apache PDFbox是一個開源的、基於Java的、支持PDF文檔生成的工具庫,它可以用於創建新的PDF文檔,修改現有的PDF文檔,還可以從PDF文檔中提取所需的內容。Apache PDFBox還包含了數個命令行工具。在此,我們只研究打印功能。

優點:功能強大,開源軟件,較完美的解決了PDF格式文件的一系列處理,使用方便。

缺點:

具體實現如下:

①直接導入maven依賴:

  1. <dependency>

  2. <groupId>org.apache.pdfbox</groupId>

  3. <artifactId>pdfbox</artifactId>

  4. <version>2.0.6</version>

  5. </dependency>

②代碼調用實現

  1. public static void main(String[] args) throws Exception {
  2.         String pdfFile = "E:\\a.pdf";//文件路徑
  3.         File file = new File(pdfFile);
  4.         String printerName = "HP MFP M436 PCL6";//打印機名包含字串
  5.         print(file,printerName);
  6.     }
  7. public static void PDFprint(File file ,String printerName) throws Exception {
  8.         PDDocument document = null;
  9.         try {
  10.             document = PDDocument.load(file);
  11.             PrinterJob printJob = PrinterJob.getPrinterJob();
  12.             printJob.setJobName(file.getName());
  13.             if (printerName != null) {
  14.                 // 查找並設置打印機
  15.                 //獲得本臺電腦連接的所有打印機
  16.                 PrintService[] printServices = PrinterJob.lookupPrintServices();                             if(printServices == null || printServices.length == 0) {
  17.                     System.out.print("打印失敗,未找到可用打印機,請檢查。");
  18.                     return ;
  19.                 }
  20.                 PrintService printService = null;
  21.                 //匹配指定打印機
  22.                 for (int i = 0;i < printServices.length; i++) {
  23.                     System.out.println(printServices[i].getName());
  24.                     if (printServices[i].getName().contains(printerName)) {
  25.                         printService = printServices[i];
  26.                         break;
  27.                     }
  28.                 }
  29.                 if(printService!=null){
  30.                     printJob.setPrintService(printService);
  31.                 }else{
  32.                     System.out.print("打印失敗,未找到名稱爲" + printerName + "的打印機,請檢查。");
  33.                     return ;
  34.                 }
  35.             }
  36.             //設置紙張及縮放
  37.             PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.ACTUAL_SIZE);
  38.             //設置多頁打印
  39.             Book book = new Book();
  40.             PageFormat pageFormat = new PageFormat();
  41.             //設置打印方向
  42.             pageFormat.setOrientation(PageFormat.PORTRAIT);//縱向
  43.             pageFormat.setPaper(getPaper());//設置紙張
  44.             book.append(pdfPrintable, pageFormat, document.getNumberOfPages());
  45.             printJob.setPageable(book);
  46.             printJob.setCopies(1);//設置打印份數
  47.             //添加打印屬性
  48.             HashPrintRequestAttributeSet pars = new HashPrintRequestAttributeSet();
  49.             pars.add(Sides.DUPLEX); //設置單雙頁
  50.             printJob.print(pars);
  51.         }finally {
  52.             if (document != null) {
  53.                 try {
  54.                     document.close();
  55.                 } catch (IOException e) {
  56.                     e.printStackTrace();
  57.                 }
  58.             }
  59.         }
  60.     }
  61. public static Paper getPaper() {
  62.         Paper paper = new Paper();
  63.         // 默認爲A4紙張,對應像素寬和高分別爲 595, 842
  64.         int width = 595;
  65.         int height = 842;
  66.         // 設置邊距,單位是像素,10mm邊距,對應 28px
  67.         int marginLeft = 10;
  68.         int marginRight = 0;
  69.         int marginTop = 10;
  70.         int marginBottom = 0;
  71.         paper.setSize(width, height);
  72.         // 下面一行代碼,解決了打印內容爲空的問題
  73.         paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
  74.         return paper;
  75.     }
     

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包-->

  1.         <dependency>
  2.             <groupId>com.jacob</groupId>
  3.             <artifactId>jacob</artifactId>
  4.             <version>1.19</version>
  5.             <scope>system</scope>
  6.         <systemPath>${basedir}/src/main/resources/lib/jacob.jar</systemPath>
  7.         </dependency>
     

具體代碼實現:

 

  1. public static void main(String[] args) {
  2.         String filePath = "E:\\a.docx";//文件路徑
  3.         String printerName = "HP MFP M436 PCL6";//打印機名包含字串
  4.         printWord(filePath,printerName);
  5.     }
  6.  
  7.     public static void printWord(String filePath, String printerName){
  8. //        初始化線程
  9.         ComThread.InitSTA();
  10.         ActiveXComponent word = new ActiveXComponent("Word.Application");
  11.        //設置打印機名稱
  12.         word.setProperty("ActivePrinter", new Variant(printerName));
  13.         // 這裏Visible是控制文檔打開後是可見還是不可見,若是靜默打印,那麼第三個參數就設爲false就好了
  14.         Dispatch.put(word, "Visible", new Variant(false));
  15.         // 獲取文檔屬性
  16.         Dispatch document = word.getProperty("Documents").toDispatch();
  17.         // 打開激活文擋
  18.         Dispatch doc=Dispatch.call(document, "Open", filePath).toDispatch();
  19.         //Dispatch doc = Dispatch.invoke(document, "Open", Dispatch.Method,
  20.               //  new Object[] { filePath }, new int[1]).toDispatch();
  21.         try{
  22.             Dispatch.callN(doc, "PrintOut");
  23.             System.out.println("打印成功!");
  24.         }catch (Exception e){
  25.             e.printStackTrace();
  26.             System.out.println("打印失敗");
  27.         }finally {
  28.             try {
  29.                 if (doc != null) {
  30.                     Dispatch.call(doc, "Close", new Variant(0));//word文檔關閉
  31.                 }
  32.             } catch (Exception e2) {
  33.                 e2.printStackTrace();
  34.             }
  35.             //退出
  36.             word.invoke("Quit", new Variant[0]);
  37.             //釋放資源
  38.             ComThread.Release();
  39.             ComThread.quitMainSTA();
  40.         }
  41.         }
     

2.3.2 先將word轉化爲pdf文件,然後打印pdf(lz使用)

優點:可設置打印參數等操作

缺點:也要引入jacob相關依賴和文件

具體實現步驟如下:

①因爲轉化也是使用jacob插件,所以也需要根據第一種方法一樣引入jacob相關依賴和文件

②打印pdf文件時,使用的是上面講述的pdfbox插件,所以也需要引入pdfbox的依賴

maven

  1.    <dependency>
  2.             <groupId>org.apache.pdfbox</groupId>
  3.             <artifactId>pdfbox</artifactId>
  4.             <version>2.0.6</version>
  5.         </dependency>

③代碼具體實現

首先將word文件轉化爲pdf文件

  1. //word轉化pdf,傳入轉換前的文件路徑(例:"E:\\a.docx")和轉換後的文件路徑(例:"E:\\a.pdf")
  2.     public static void wordToPDF(String sFilePath,String toFilePath) {
  3.         System.out.println("啓動 Word...");
  4.         long start = System.currentTimeMillis();
  5.         ActiveXComponent app = null;
  6.         Dispatch doc = null;
  7.         try {
  8.             app = new ActiveXComponent("Word.Application");
  9.             app.setProperty("Visible", new Variant(false));
  10.             Dispatch docs = app.getProperty("Documents").toDispatch();
  11.             doc = Dispatch.call(docs, "Open", sfilePath).toDispatch();
  12.             System.out.println("打開文檔:" + sfilePath);
  13.             System.out.println("轉換文檔到 PDF:" + toFilePath);
  14.             File tofile = new File(toFilePath);
  15.             if (tofile.exists()) {
  16.                 tofile.delete();
  17.             }
  18.             Dispatch.call(doc, "SaveAs", toFilePath, // FileName
  19.                     17);//17是pdf格式
  20.             long end = System.currentTimeMillis();
  21.             System.out.println("轉換完成..用時:" + (end - start) + "ms.");
  22.  
  23.         } catch (Exception e) {
  24.             System.out.println("========Error:文檔轉換失敗:" + e.getMessage());
  25.         } finally {
  26.             Dispatch.call(doc, "Close", false);
  27.             System.out.println("關閉文檔");
  28.             if (app != null)
  29.                 app.invoke("Quit", new Variant[]{});
  30.         }
  31.         // 如果沒有這句話,winword.exe進程將不會關閉
  32.         ComThread.Release();
  33.     }
     

然後打印pdf文件(這裏傳入的文件爲上面word轉化生成的pdf文件)

  1. //這裏傳入的文件爲word轉化生成的pdf文件
  2. public static void PDFprint(File file ,String printerName) throws Exception {
  3.         PDDocument document = null;
  4.         try {
  5.             document = PDDocument.load(file);
  6.             PrinterJob printJob = PrinterJob.getPrinterJob();
  7.             printJob.setJobName(file.getName());
  8.             if (printerName != null) {
  9.                 // 查找並設置打印機
  10.                 //獲得本臺電腦連接的所有打印機
  11.                 PrintService[] printServices = PrinterJob.lookupPrintServices();                             if(printServices == null || printServices.length == 0) {
  12.                     System.out.print("打印失敗,未找到可用打印機,請檢查。");
  13.                     return ;
  14.                 }
  15.                 PrintService printService = null;
  16.                 //匹配指定打印機
  17.                 for (int i = 0;i < printServices.length; i++) {
  18.                     System.out.println(printServices[i].getName());
  19.                     if (printServices[i].getName().contains(printerName)) {
  20.                         printService = printServices[i];
  21.                         break;
  22.                     }
  23.                 }
  24.                 if(printService!=null){
  25.                     printJob.setPrintService(printService);
  26.                 }else{
  27.                     System.out.print("打印失敗,未找到名稱爲" + printerName + "的打印機,請檢查。");
  28.                     return ;
  29.                 }
  30.             }
  31.             //設置紙張及縮放
  32.             PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.ACTUAL_SIZE);
  33.             //設置多頁打印
  34.             Book book = new Book();
  35.             PageFormat pageFormat = new PageFormat();
  36.             //設置打印方向
  37.             pageFormat.setOrientation(PageFormat.PORTRAIT);//縱向
  38.             pageFormat.setPaper(getPaper());//設置紙張
  39.             book.append(pdfPrintable, pageFormat, document.getNumberOfPages());
  40.             printJob.setPageable(book);
  41.             printJob.setCopies(1);//設置打印份數
  42.             //添加打印屬性
  43.             HashPrintRequestAttributeSet pars = new HashPrintRequestAttributeSet();
  44.             pars.add(Sides.DUPLEX); //設置單雙頁
  45.             printJob.print(pars);
  46.         }finally {
  47.             if (document != null) {
  48.                 try {
  49.                     document.close();
  50.                 } catch (IOException e) {
  51.                     e.printStackTrace();
  52.                 }
  53.             }
  54.         }
  55.     }
  56. public static Paper getPaper() {
  57.         Paper paper = new Paper();
  58.         // 默認爲A4紙張,對應像素寬和高分別爲 595, 842
  59.         int width = 595;
  60.         int height = 842;
  61.         // 設置邊距,單位是像素,10mm邊距,對應 28px
  62.         int marginLeft = 10;
  63.         int marginRight = 0;
  64.         int marginTop = 10;
  65.         int marginBottom = 0;
  66.         paper.setSize(width, height);
  67.         // 下面一行代碼,解決了打印內容爲空的問題
  68.         paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
  69.         return paper;
  70.     }
     

 

最後別忘了將生成的pdf文件刪除

  1. File file=new File(toFilePath);

  2. if(file.exists()&&file.isFile())

  3. file.delete();

三、總結

至此,本次實現的JPG、PDF和Word三種文件格式的打印已經全部實現,分別採用了原生打印和PDFbox插件和jacob插件進行實現。記錄一下,以防忘記,留待後續使用。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章