1. 程式人生 > >java中如何將office檔案轉成pdf或者圖片(親測有效)

java中如何將office檔案轉成pdf或者圖片(親測有效)

前段時間做專案時,需要將word文件在瀏覽器中開啟,一般的在瀏覽器中開啟word都是直接提示下載的,找了好久都是些pageoffice等的收費外掛,小專案成本要儘量壓縮,所以就放棄了這種收費的外掛了。突然想到有些瀏覽器能直接開啟pdf或者圖片,手機端也需要顯示圖片,所以可以將word轉成pdf和圖片,那java中怎麼將word轉成pdf或者圖片呢?也研究了一下,有的說用poi等,但是研究了一下,發現不好用,另一種辦法是office中的轉換jar包:jacob,通過他可以呼叫office中的檔案轉換功能:比如說將word轉成pdf或圖片,excel轉成pdf或圖片,ppt轉成pdf或圖片等等,所以就用了這種辦法,下面說一下具體的操作過程,在開始前首先需要準備一些材料:jacob和office,我這裡用的是jacob1.11.1和office2010,具體過程如下:

1.先安裝一下office2010;

2.解壓下載的jacob1.11.1,將裡面的jacob.jar匯入專案中,buildPath,如果是win732位系統,找到x86資料夾中的jacob.dll,拷貝到c盤windows的system32目錄下(64位系統找到AMD64資料夾中的jacob.dll,同樣拷貝到system32目錄下);

下面就開始在專案中寫程式碼完成轉換了。

public class JacobUtil {
	
	   public static final String DOC = "doc";
	   public static final String DOCX = "docx";
	   public static final String PDF = "pdf";
	   public static final String XLS = "xls";
	   public static final String XLSX = "xlsx";
	   public static final String MP4 = "mp4";
	   public static final String PPT = "ppt";
	   public static final String PPTX = "pptx";
	
        // 8 代表word儲存成html  
        public static final int WORD2HTML = 8;  
        // 17代表word儲存成pdf
        public static final int WD2PDF = 17;
        public static final int PPT2PDF = 32;
        public static final int XLS2PDF = 0;
    
    public static void main(String[] args) {   
    	String pptfile = "C:/Users/Administrator/Desktop/ceshi.pptx";  
    	String pdffile = "C:/Users/Administrator/Desktop/數字類比電路.pdf";  
        ppt2pdf(pptfile,pdffile);  
        pdf2Image(pdffile);
    }  
      
         /**
	 * @author shenjianhu: 
	 * @version 建立時間:2017年4月8日 下午9:07:33
	 * @param resourceType 資源型別
	 * @param path 資源路徑
	 * @return
	 * TODO 檔案轉換
	 */
	public static Integer formatConvert(String resourceType, String resourcePath) {
		Integer pages = 0;
		String resource = resourcePath.substring(0, resourcePath.lastIndexOf("."));
		if(resourceType.equalsIgnoreCase(DOC)||resourceType.equalsIgnoreCase(DOCX)){
			//word轉成pdf和圖片
			word2pdf(resourcePath, resource+".pdf");
			pages = pdf2Image(resource+".pdf");
		}else if(resourceType.equalsIgnoreCase(PDF)){
			//pdf轉成圖片
			pages = pdf2Image(resourcePath);
		}else if(resourceType.equalsIgnoreCase(XLS)||resourceType.equalsIgnoreCase(XLSX)){
			//excel檔案轉成圖片
			excel2pdf(resourcePath, resource+".pdf");
			pages = pdf2Image(resource+".pdf");
		}else if(resourceType.equalsIgnoreCase(PPT)||resourceType.equalsIgnoreCase(PPTX)){
			//ppt2pdf(resourcePath, resource+".pdf");
			//pages = pdf2Image(resource+".pdf");
			pages = ppt2Image(resourcePath, resource+".jpg");
		}else if(resourceType.equalsIgnoreCase(MP4)){
			//視訊檔案不轉換
			pages = 0;
		}
		return pages;
	}
    
    /**
     * @author shenjianhu: 
     * @version 建立時間:2017年4月18日 下午3:08:11
     * @param pptfile
     * @param imgfile
     * TODO  ppt轉換成圖片
     */
    public static Integer ppt2Image(String pptfile,String imgfile){
    	String imageDir = pptfile.substring(0, pptfile.lastIndexOf("."));
    	File dir = new File(imageDir);
    	if(!dir.exists()){
    		dir.mkdirs();
    	}
    	int length = 0;
    	ActiveXComponent app = null;
    	try{
    		 ComThread.InitSTA();
    		 app = new ActiveXComponent("PowerPoint.Application"); 
    		 System.out.println("準備開啟ppt文件");
    		 app.setProperty("Visible", true);
    		 Dispatch ppts = app.getProperty("Presentations").toDispatch();
    		 Dispatch ppt = Dispatch.call(ppts, "Open", pptfile, true, true, true).toDispatch();
    		 System.out.println("-----------------ppt開始轉換圖片---------------");
    		 Dispatch.call(ppt, "SaveCopyAs", imgfile, 17);
    		 System.out.println("-----------------ppt轉換圖片結束---------------");
    		 Dispatch.call(ppt, "Close");    		 
    		 System.out.println("關閉ppt文件");    		 
    	}catch(Exception e){
    		 ComThread.Release();
    		 e.printStackTrace();
    	}finally{
    		 String files[];
    		 files = dir.list();
    		 length = files.length;
    		 System.out.println(length);
    		 app.invoke("Quit");    		 
    		 ComThread.Release();
    	}
    	return length;
    }
    
    /**   
     * WORD轉HTML   
     * @param docfile WORD檔案全路�?  
     * @param htmlfile 轉換後HTML存放路徑   
     */
    public static void wordToHtml(String docfile, String htmlfile)     
    {     
        // 啟動word應用程式(Microsoft Office Word 2003)  
        ActiveXComponent app = null; 
        System.out.println("*****正在轉換...*****");  
        try    
        {   
        	ComThread.InitSTA();
        	app = new ActiveXComponent("Word.Application");
            // 設定word應用程式不可�?   
            app.setProperty("Visible", new Variant(false));    
            // documents表示word程式的所有文件視窗,(word是多文件應用程式�? 
            Dispatch docs = app.getProperty("Documents").toDispatch();    
            // 開啟要轉換的word檔案  
            Dispatch doc = Dispatch.invoke(     
                    docs,     
                    "Open",     
                    Dispatch.Method,     
                    new Object[] { docfile, new Variant(false),   
                            new Variant(true) }, new int[1]).toDispatch();     
            // 作為html格式儲存到臨時文�? 
            Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {     
                    htmlfile, new Variant(WORD2HTML) }, new int[1]);     
            // 關閉word檔案  
            
            
            Dispatch.call(doc, "Close", new Variant(false));     
        }     
        catch (Exception e)     
        {     
        	ComThread.Release();
            e.printStackTrace();     
        }     
        finally    
        {     
            //關閉word應用程式  
            app.invoke("Quit", new Variant[] {});   
            ComThread.Release();
        }   
        System.out.println("*****轉換完畢********");  
    } 
    
    public static void word2pdf(String docfile, String pdffile)     
    {     
        // 啟動word應用程式(Microsoft Office Word 2003)  
        ActiveXComponent app = null;  
        try{
        	ComThread.InitSTA();
        	app = new ActiveXComponent("Word.Application");     
        	app.setProperty("Visible", false);
        	System.out.println("*****正在轉換...*****");  
            // 設定word應用程式不可見
           // app.setProperty("Visible", new Variant(false));    
            // documents表示word程式的所有文件視窗,(word是多文件應用程式�? 
            Dispatch docs = app.getProperty("Documents").toDispatch();    
            // 開啟要轉換的word檔案  
           /* Dispatch doc = Dispatch.invoke(     
                    docs,     
                    "Open",     
                    Dispatch.Method,     
                    new Object[] { docfile, new Variant(false),   
                            new Variant(true) }, new int[1]).toDispatch(); */
            
            Dispatch doc = Dispatch.call(
                    docs,     
                    "Open",
                    docfile,
                    false,
                    true).toDispatch();     
            // 呼叫Document物件的saveAs方法,將文件儲存為pdf格式
            /*Dispatch.invoke(doc, "ExportAsFixedFormat", Dispatch.Method, new Object[] {     
            		pdffile, new Variant(wdFormatPDF) }, new int[1]);*/  
            
            Dispatch.call(doc, "ExportAsFixedFormat", pdffile, WD2PDF);  
            // 關閉word檔案  
            Dispatch.call(doc, "Close", false); 
        }     
        catch (Exception e)     
        {   ComThread.Release();  
            e.printStackTrace();    
        }     
        finally    
        {     
            //關閉word應用程式  
            app.invoke("Quit", 0);   
            ComThread.Release();
        }   
        System.out.println("*****轉換完畢********");  
    }
    
    /**
     * @author shenjianhu: 
     * @version 建立時間:2016年11月16日 下午8:21:29
     * @param pdffile
     * TODO pdf檔案按頁轉成圖片
     */
    public static int pdf2Image(String pdffile){     
        File file = new File(pdffile);
        int pages = 0;
        try {
        	ComThread.InitSTA();
			RandomAccessFile raf = new RandomAccessFile(file, "r");
			FileChannel channel = raf.getChannel();
			java.nio.ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
			PDFFile pdf = new PDFFile(buf);
			pages = pdf.getNumPages();
			System.out.println("頁數:"+pdf.getNumPages());
			File direct = new File(pdffile.substring(0, pdffile.lastIndexOf(".")));
			if(!direct.exists()){
				direct.mkdir();
			}
			for(int i=1;i<=pdf.getNumPages();i++){
				PDFPage page = pdf.getPage(i);
				Rectangle rect = new Rectangle(0, 0, (int)(page.getBBox().getWidth()), (int)(page.getBBox().getHeight()));
				int width = (int) (rect.getWidth()*2);
				int height = (int) (rect.getHeight()*2);
				Image image = page.getImage(width, height, rect, null, true, true);
				BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
				tag.getGraphics().drawImage(image, 0, 0, width, height, null);
				FileOutputStream out = new FileOutputStream(direct+"/幻燈片"+i+".JPG");
				JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
				JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(tag);
				param.setQuality(1f, false);
				encoder.setJPEGEncodeParam(param);
				encoder.encode(tag);
				out.close();
				System.out.println("image in the page -->"+i);
			}
			buf.clear();
			channel.close();
			raf.close();
			unmap(buf);
		} catch (Exception e) {
			ComThread.Release();
			e.printStackTrace();
		} finally{
			ComThread.Release();
		}
        return pages;
    }
    
    /**
     * @author shenjianhu: 
     * @version 建立時間:2016年12月19日 上午11:25:22
     * @param buffer
     * TODO pdf轉成圖片時解除對映,以便後面刪除檔案時能夠刪除pdf檔案
     */
    
    
    
    public static <T> void unmap(final Object buffer){
    	AccessController.doPrivileged(new PrivilegedAction<T>() {
			@Override
			public T run() {
				try{
					Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]);
					getCleanerMethod.setAccessible(true);
					Cleaner cleaner = (Cleaner) getCleanerMethod.invoke(buffer, new Object[0]);
					cleaner.clean();
				}catch(Exception e){
					e.printStackTrace();
				}
				return null;
			}
		});
    }
    
    public static void ppt2pdf(String pptfile,String pdffile){
    	Log.debug("開啟ppt應用");
    	ActiveXComponent app = null;
    	Log.debug("設定可見性");
    	//app.setProperty("Visible", new Variant(false));
    	Log.debug("開啟ppt檔案");
    	try {
    		ComThread.InitSTA();
    		app = new ActiveXComponent("PowerPoint.Application");
    		Dispatch files = app.getProperty("Presentations").toDispatch();
        	Dispatch file = Dispatch.call(files, "open", pptfile, false, true).toDispatch();
        	Log.debug("儲存為圖片");
        	Dispatch.call(file, "SaveAs", pdffile, PPT2PDF);
        	Log.debug("關閉文件");
        	Dispatch.call(file,"Close");
		} catch (Exception e) {
			ComThread.Release();
			e.printStackTrace();
			Log.error("ppt to images error",e);
			//throw e;
		}finally{
			Log.debug("關閉應用");
			app.invoke("Quit");
			ComThread.Release();
		}
    }
    
    public static void excel2pdf(String excelfile,String pdffile){
    	ActiveXComponent app = null;
    	try{
    		ComThread.InitSTA(true);
    		app = new ActiveXComponent("Excel.Application");
	    	app.setProperty("Visible", false);
	    	app.setProperty("AutomationSecurity", new Variant(3));//禁用巨集
	    	Dispatch excels = app.getProperty("Workbooks").toDispatch();
	    	/*Dispatch excel = Dispatch.invoke(excels, "Open", Dispatch.Method, new Object[]{
	    			excelfile,
	    			new Variant(false),
	    			new Variant(false),
	    	},new int[9]).toDispatch();*/
	    	Dispatch excel = Dispatch.call(excels, "Open", 
	    			excelfile,false,true).toDispatch();
	    	//轉換格式ExportAsFixedFormat
	    	/*Dispatch.invoke(excel, "ExportAsFixedFormat", Dispatch.Method, new Object[]{
	    			new Variant(0),//pdf格式=0
	    			pdffile,
	    			new Variant(0)//0=標準(生成的pdf圖片不會變模糊) 1=最小檔案(生成的pdf圖片模糊的一塌糊塗)
	    	}, new int[1]);*/
	    	Dispatch.call(excel, "ExportAsFixedFormat",XLS2PDF,
	    			pdffile);
	    	Dispatch.call(excel, "Close", false);
	    	if(app!=null){
	    		app.invoke("Quit");
	    		app=null;
	    	}
    	}catch(Exception e){
    		ComThread.Release();
    		e.printStackTrace();
    	}finally{
    		ComThread.Release();
    	}
    }
    
    public static void ppt2html(String pptfile,String htmlfile){
    	ActiveXComponent app = null;
    	try{
    		ComThread.InitSTA(true);
    		app = new ActiveXComponent("PowerPoint.Application");
	    	//app.setProperty("Visible", false);
	    	app.setProperty("AutomationSecurity", new Variant(3));//禁用巨集
	    	Dispatch dispatch = app.getProperty("Presentations").toDispatch();
	    	Dispatch dispatch1 = Dispatch.call(dispatch, "Open", 
	    			pptfile,false,true).toDispatch();
	    	Dispatch.call(dispatch1, "SaveAs",
	    			htmlfile,new Variant(12));
	    	Dispatch.call(dispatch1, "Close", false);
	    	if(app!=null){
	    		app.invoke("Quit");
	    		app=null;
	    	}
    	}catch(Exception e){
    		ComThread.Release();
    		e.printStackTrace();
    	}finally{
    		ComThread.Release();
    	}
    }

}
寫好程式碼後,根據自己的需要呼叫相應的方法就行了。需要注意的是:檔案路徑中最好不好出現空格,出現空格可能jacob程式訪問不到資源報錯。