關於itext使用過程中遇到的問題總結

環境介紹:

itext目前已經發展到itext7版本,目前系統裏面使用的itext2版本;

使用spring的freemaker結合itext,完成pdf的導出

需要進行pdf導出的html文件,可能包含下面這幾種情況,導致pdf導出失敗:

  1. 含有不閉合的html標籤,比如<br>
  2. html標籤中,含有非法的屬性,比如 v:data="xxx"
  3. img標籤不是引用的http,而是base64之類的
  4. 設置了特殊字體的,pdf導出雖然不失敗,但是內容看不到
  5. img圖片過大的時候,pdf導出會出現截圖的現象

針對上面的幾個問題,解決思路

1,研究itext代碼,重寫html解析相關的類

2,使用html處理工具,對html文件進行合法性處理(比如:jsoup)

選第二種方案(第一個費時間,沒有太多的精力研究)

 

結合jsoup,對html文件進行處理,核心代碼:

對html文件進行合法性處理

	/**
	 * 1,html標籤對齊
	 * 2,檢查所有的img標籤,如果爲base64編碼就去掉該圖片
	 * 3,過濾所有的html標籤,僅保留styles和class兩個屬性,其他的屬性去掉
	 * 4,檢查字體設置,如果有字體設置,但是沒有SimSun字體,增加SimSun
	 * @param bodyHtml
	 * @return
	 */
	public static String correctBody(String bodyHtml){
		if(bodyHtml==null || "".equals(bodyHtml)) {
			return "";
		}
		//1,html標籤對齊
		Document doc = Jsoup.parseBodyFragment(bodyHtml);
	   //2,檢查所有的img標籤,如果爲base64編碼就去掉該圖片
       Elements elements=doc.getElementsByTag("img");
       for(Element element : elements) {
           String imgSrc=element.attr("src"); //獲取src屬性的值
           if(imgSrc.indexOf("data:image")>-1){
        	   element.attr("alt","該圖片不支持導出");
        	   element.attr("src"," ");
           }else{  
        	   String width = element.attr("width");
        	   int num = getNumber(width);        	   
        	   if(num==Integer.MAX_VALUE){
        		  int  realWidth = FileTool.imageWidth(imgSrc);
        		  if(realWidth > 550){
        			  element.attr("width","550");
        		  }
        	   }else if(num > 550){
        		   element.attr("width","550");
        	   }else{
        		   //do nothing 
        	   }
           }
       }
       //3,過濾所有的html標籤,僅保留styles和class兩個屬性,其他的屬性去掉
       Whitelist wl = Whitelist.relaxed();
       for(int i=0;i<htmlTags.length;i++){
    	   wl.addTags(htmlTags[i]);
       }             
       wl.addAttributes("input", "type","value");            
       wl.addAttributes(":all", "class","styles","style"); 
       
       //4,檢查字體設置,如果有字體設置,但是沒有SimSun字體設置,增加SimSun
       addFontFamliy(doc.getAllElements());
       
       Cleaner cleaner = new Cleaner(wl);
       Document clean = cleaner.clean(doc);
       String str = clean.body().outerHtml();
       return  str;
	}

關於圖片的處理,從本地環境,獲取圖片的寬度

/**
	 * 計算width對應的寬度
	 * 如果沒有寬度設置,設置爲Integer.MAX_VALUE
	 * 否則就是width對應的寬度
	 * @param str
	 * @return
	 */
	private static int getNumber(String str){
		StringBuffer sbuf = new StringBuffer();
		int num = Integer.MAX_VALUE;
		if(str != null && !"".equals(str)){
			for(int i=0;i<str.length();i++){
				if(str.charAt(i)>=48 && str.charAt(i)<=57){
					sbuf.append(str.charAt(i));
				}
			}	
			if(sbuf.length()>0){
				num = Integer.valueOf(sbuf.toString());
			}
		}
		return num;
	}

最終的處理:

	public static String  correctHtml(String bodyHtml){
//		1,html標籤對齊
//		2,檢查所有的img標籤,如果爲base64編碼就去掉該圖片
//		3,過濾所有的html標籤,僅保留styles和class兩個屬性,其他的屬性去掉
//		4,檢查字體設置,如果有字體設置,但是沒有SimSun字體,增加SimSun
		String str = JsStringUtils.correctBody(bodyHtml);
		

//		5,填空題
       str = str.replaceAll("(<input)([^>]+)(>)", "__________");
       
//		6,pdf要求嚴格的html
       str = str.replaceAll("<br>", "<br/>");
//       str = str.replaceAll("(<img)([^>]+)(>)", "$1$2 />");
//       str = str.replaceAll("(<input)([^>]+)(>)", "$1$2 />");
       
//       7,去掉多餘的body       
       str = str.replaceAll("<body>", "");
       str = str.replaceAll("</body>", "");
//       System.out.println("-----------------------------------");
//       System.out.println(str);
	   return str;
	}

 

 

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