• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head lang="en">
      <meta http-equiv="content-type" content="text/html;charset=utf-8"></meta>
      <title>軟件包隱患掃描報告</title>
      <style>
        .template_ftl {
          width: 100%;
          height: 100%;
          padding: 30px 25px;
        }
    
        .template_box {
          width: 600px;
          height: 842px;
          box-sizing: border-box;
          margin: 0 auto;
        }
    
        .template_ftl .template_header {
    
          width: 100%;
          height: 50px;
          box-sizing: border-box;
          color: #0D122B;
        }
    
        .template_ftl .template_header > i {
          display: inline-block;
          width: 24px;
          height: 28px;
          background: url("stack.png") no-repeat center center;
        }
    
        .template_ftl .template_header > h2 {
          display: inline-block;
          font-size: 17px;
        }
    
        .template_ftl .template_header > div {
          float: right;
          color: #B7C1CF;
          font-size: 9px;
          line-height: 50px;
        }
    
        .template_ftl .template_header > div > i {
          display: inline-block;
          width: 9px;
          height: 9px;
          background: url("Calendar.png") no-repeat center center;
        }
    
        .template_ftl .template_description {
          width: 100%;
          margin-top: 10px;
        }
    
        .template_ftl .template_title {
          width: 100%;
          height: 18px;
          line-height: 18px;
          color: #00AEA1;
          font-size: 12px;
        }
    
        .template_ftl .template_title > i {
          display: inline-block;
          width: 14px;
          height: 14px;
          margin-right: 10px;
          background: url("Layers.png") no-repeat center center;
        }
    
        .template_ftl .template_info {
          list-style: none;
          padding-left: 30px;
        }
    
        .template_ftl .template_info label {
          display: inline-block;
          width: 80px;
          margin-right: 30px;
          color: #646464;
          font-size: 10px;
          vertical-align: middle;
        }
    
        .template_ftl .template_info span {
          color: #0D122B;
          font-size: 10px;
          vertical-align: middle;
        }
    
        .template_ftl .template_info li {
          margin-bottom: 5px;
        }
    
        .template_ftl .template_title .shield {
          width: 14px;
          height: 14px;
          background: url("Shield.png") no-repeat center center;
        }
    
        .template_ftl .template_title .screen {
          width: 14px;
          height: 14px;
          background: url("Screen.png") no-repeat center center;
        }
    
        .template_ftl .template_network {
          list-style: none;
          padding-left: 30px;
          margin-top: 10px;
        }
    
        .template_ftl .template_network .network_level b {
          color: #0D122B;
          font-size: 12px;
        }
    
        .template_ftl .template_network .network_level span {
          color: #E74C3C;
          font-size: 12px;
        }
    
        .template_ftl .template_network .network_level p {
          margin: 0;
          color: #646464;
          font-size: 10px;
        }
    
        .template_ftl .template_network .network_content:before {
          content: '● ';
          color: #00AEA1;
        }
    
        .template_ftl .template_network .network_content {
          color: #3E4550;
          font-size: 10px;
          margin-top: 10px;
        }
    
        .online_info {
          width: 100%;
        }
    
        .online_info .online_list {
          width: 100%;
         
          box-sizing: border-box;
          list-style: none;
          padding-left: 30px;
          display: flex;
          flex-flow: row nowrap;
          justify-content: space-between;
          align-items: center;
          margin: 0;
          color:#3E4550;
          font-size: 10px;
        }
        .online_info .online_list:nth-child(2n){
          background-color: #EFEFEF;
        }
        .online_info .online_list > td {
          width: 90px;
          line-height: 25px;
          text-align: center;
         
        }
        .online_info .online_list > td:first-child {
          text-align: center;
        }
         
      </style>
    </head>
    <body>
    <div class="template_ftl" style="font-family:SimSun;">
    
      <div class="template_box">
        <div class="template_header">
          <i></i>
    
          <span style="font-size:24px;font-weight:1px bold;">軟件包掃描報告</span>
    
          <div>
            <i></i>
            <span>
            	<#if (currentDate)??>
            		${currentDate}
            	</#if>
            </span>
          </div>
        </div>
        <div class="template_description">
          <div class="template_title">
            <i></i>
            <span>掃描概要信息</span>
          </div>
          <ul class="template_info">
            <li>
              <label>掃描產品名稱</label>
              <span>
              	<#if (softScanInfo.productName)??>
    				${softScanInfo.productName}
    			</#if>
    		 </span>
            </li>
            <li>
              <label>文件路徑</label>
              <span>
    		  		<#if (softScanInfo.scanFilePath)??>
    					${softScanInfo.scanFilePath}
    				</#if>
    		  </span>
            </li>
            <li>
              <label>掃描開始時間</label>
              <span>
              	<#if (softScanInfo.scanBegintime)??>
    				${(softScanInfo.scanBegintime)?string("yyyy年MM月dd日 HH:mm:ss")}
    			</#if>
              </span>
            </li>
            <li>
              <label>掃描結束時間</label>
              <span>
              	<#if (softScanInfo.scanEndtime)??>
    				${(softScanInfo.scanEndtime)?string("yyyy年MM月dd日 HH:mm:ss")}
    			</#if>
              </span>
            </li>
          </ul>
        </div>
        <div class="template_description">
          <div class="template_title">
            <i class="shield"></i>
            <span>軟件包安全信息</span>
          </div>
          <ul class="template_network">
            <li class="network_level">
              <span style="font-size:13px;color:black;">軟件包風險等級為 </span>
    		  
    		  	<#if (softScanInfo.scanResult)??>
    				<#if (softScanInfo.scanResult == '高')>
    					<span style="color:red;">${softScanInfo.scanResult}</span>
    					<#elseif (softScanInfo.scanResult == '中')>
    						<span style="color:#FF9900;">${softScanInfo.scanResult}</span>
    					<#elseif (softScanInfo.scanResult == '低')>
    						<span style="color:#0000FF;">${softScanInfo.scanResult}</span>
    					<#else> 
    						<span style="color:#00cc00;">安全</span>
    				</#if>
    			<#else>
    				<span style="color:#00cc00;">安全</span>
    		    </#if>
              <p style="margin-top:8px;">本次共掃描1個軟件包,其中包含<#if recordList?exists>${recordList?size} <#else>0</#if>款軟件</p>
            </li>
    		<li class="network_content">
              <span>
              		風險等級為<span style="color:red;">高</span>的軟件數為
    				<span style="color:red;"><#if (highRiskRecord.appScanResult)??>${highRiskRecord.appScanResult}</span></#if>
    		  </span>
            </li>
    		<li class="network_content">
              <span>
              		風險等級為<span style="color:#FF9900;">中</span>的軟件數為
    				<span style="color:#FF9900;"><#if (middleRiskRecord.appScanResult)??>${middleRiskRecord.appScanResult}</span></#if>
    		  </span>
            </li>
    		<li class="network_content">
              <span>
              		風險等級為<span style="color:#0000FF;">低</span>的軟件數為
    				<span style="color:#0000FF;"><#if (lowRiskRecord.appScanResult)??>${lowRiskRecord.appScanResult}</span></#if>
    		  </span>
            </li>
    		<li class="network_content">
              <span>
              		風險等級為<span style="color:#00cc00;">安全</span>的軟件數為
    				 <span style="color:#00cc00;"><#if (noneRiskRecord.appScanResult)??>${noneRiskRecord.appScanResult}</span></#if>
    		  </span>
            </li>
          </ul>
        </div>
        <div class="template_description">
          <div class="template_title">
            <i class="screen"></i>
            <span>掃描軟件包概要信息</span>
          </div>
          <div class="online_info" >
    	     <table class="online_list" style="word-break: break-all; word-wrap: break-word;">
    	        <tr class="online_list" style="border-bottom: 1px solid #B7C1CF;color: #94949;">
    	          <td >軟件名稱</td>
    	          <td style="width:120px;">版本號</td>
    	          <td style="width:150px;">軟件包名稱</td>
    	          <td style="width:40px;">安全風險</td>
    	          <td style="width:150px;">安全描述事件</td>
    	          <td style="width:30px;">通過</td>
    	        </tr>
    	        <#if recordList?exists>
    				<#list recordList as record>
    					<tr class="online_list" >
    						<td>
    							<#if (record.appName)??>
    								${record.appName}
    							</#if>
    						</td>
    				        <td style="width:120px;">
    				        	<#if (record.appVersion)??>
    								${record.appVersion}
    							</#if>
    				        </td>
    				        <td style="width:150px;">
    				        	<#if (record.appFileName)??>
    								${record.appFileName}
    							</#if>
    				        </td>
    				        <td style="width:30px;">
    				        	<#if (record.riskRating)??>
    				        		<#if (record.riskRating == '無')>
    				        			安全
    				        		<#else>
    									${record.riskRating}
    								</#if>
    							<#else>
    								安全
    							</#if>
    				        </td>
    				        <td style="width:150px;">
    							<#if (record.riskDescription)??>
    								${record.riskDescription}
    							<#else>
    								無
    							</#if>
    						</td>
    				        <td style="width:20px;">
    				        	<#if (record.appScanResult)??>
    				        		<#if (record.appScanResult = 1)>
    						           <i style="color: #00AEA1">√</i>
    				        		<#else>
    				        			<i style="color: #E74C3C">×</i>
    				        		</#if>
    							<#else>
    								<i style="color: #00AEA1">√</i>
    							</#if>
    				        </td>
    					</tr>
    				</#list>
    			</#if>
    		</table>
          </div>
        </div>
      </div>
    </div>
    </body>
    </html>

    2. 獲取模板,并將所獲取的數據加載生成html文件

    public String getHtmlString (final Object data, final String templateDirectory, final String templateName, final String encoding) {
    	log.info("FreeMarkerUtil!");
    	String html = null;
    	StringWriter stringWriter = null;
    	BufferedWriter writer = null;
    	try {
    		//創建一個負責管理FreeMarker模板的Configuration實例
    		final Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
    		//指定FreeMarker模板文件位置
    //		configuration.setDirectoryForTemplateLoading(new File(templateDirectory));
    			
    		//設置模板的編碼格式
    		configuration.setEncoding(Locale.CHINA, encoding);
    		//獲取模板
    		configuration.setClassForTemplateLoading(this.getClass(), "/templates");
    		final Template template = configuration.getTemplate(templateName, encoding);
    		stringWriter = new StringWriter();
    		writer = new BufferedWriter(stringWriter);
    		//將數據輸出到html中
    		template.process(data, writer);
    		writer.flush();
    		html = stringWriter.toString();
    	} catch (Exception e) {
    		log.error("failed to get html String!", e);
    	} finally {
    		if (stringWriter !=null) {
    			try {
    				stringWriter.close();
    			} catch (IOException e) {
    				log.error("failed to close writer!", e);
    			}
    		}
    		if (writer !=null) {
    			try {
    				writer.close();
    			} catch (IOException e) {
    				log.error("failed to close writer!", e);
    			}
    		}
    	}
    	log.info("getHtmlString() exit!");
    	return html;
    }

    2. 生成PDF文件

    final File file = new File(reportPath);
    try {
         if (!file.exists()) {
              file.createNewFile();
         }
         final String chineseFont = getChineseFont();//獲取字體文件路徑
         log.info("chineseFont=" + chineseFont);
         createPDF(new FileOutputStream(file), chineseFont, html);
         
    } 
    public void createPDF(final OutputStream outputStream, final String fontPath, final String html) {
            final ITextRenderer renderer = new ITextRenderer();
            // 設置字體樣式
            try {
                renderer.getFontResolver().addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                //這里的字體必須和ftl模板中的字體一致,否則中文會丟失
                // 把html代碼傳入渲染器中
                renderer.setDocumentFromString(html);
                /*
                 * 解決圖片的相對路徑問題,必須在設置document后再設置圖片路徑,不然不起作用,
                 * 如果使用絕對路徑依然有問題,可以在路徑前面加"file:/"
                 */
                // renderer.getSharedContext().setBaseURL("file:/C:/Users/HYH/Desktop/templateftp/");
                renderer.getSharedContext().setBaseURL("file:" + getPictureDirctory());
                log.info("images directory path: file:" + getPictureDirctory());
    
                renderer.layout();
                renderer.createPDF(outputStream, false);
                renderer.finishPDF();
                outputStream.flush();
            } catch (final Exception e) {
                log.error("failed to create pdf!", e);
            } finally {
                if (outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (final IOException e) {
                        log.error("failed to close outputStream!", e);
                    }
                }
            }
            log.info("create pdf completely!");
        }

    其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件;

    //獲取圖片目錄位置
        private String getPictureDirctory () {
        	final File fileDir = new File("System.getProperty("user.dir") + "/images/"");
        	if (!fileDir.exists()) {
        		fileDir.mkdirs();
        		final InputStream calendarStream = getClass().getClassLoader().getResourceAsStream("images/Calendar.png");
        		final InputStream deleteStream = getClass().getClassLoader().getResourceAsStream("images/delete.png");
        		final InputStream layersStream = getClass().getClassLoader().getResourceAsStream("images/Layers.png");
        		final InputStream saveStream = getClass().getClassLoader().getResourceAsStream("images/save.png");
        		final InputStream screenStream = getClass().getClassLoader().getResourceAsStream("images/Screen.png");
        		final InputStream shieldStream = getClass().getClassLoader().getResourceAsStream("images/Shield.png");
        		final InputStream stackStream = getClass().getClassLoader().getResourceAsStream("images/stack.png");
        		
        		final File calendarFile = new File(IMAGES_TEMP_PATH + "Calendar.png");
        		final File deleteFile = new File(IMAGES_TEMP_PATH + "delete.png");
        		final File layersFile = new File(IMAGES_TEMP_PATH + "Layers.png");
        		final File saveFile = new File(IMAGES_TEMP_PATH + "save.png");
        		final File screenFile = new File(IMAGES_TEMP_PATH + "Screen.png");
        		final File shieldFile = new File(IMAGES_TEMP_PATH + "Shield.png");
        		final File stackFile = new File(IMAGES_TEMP_PATH + "stack.png");
        		
        		try {
    				FileUtils.copyInputStreamToFile(calendarStream, calendarFile);
    				FileUtils.copyInputStreamToFile(deleteStream, deleteFile);
    				FileUtils.copyInputStreamToFile(layersStream, layersFile);
    				FileUtils.copyInputStreamToFile(saveStream, saveFile);
    				FileUtils.copyInputStreamToFile(screenStream, screenFile);
    				FileUtils.copyInputStreamToFile(shieldStream, shieldFile);
    				FileUtils.copyInputStreamToFile(stackStream, stackFile);
    			} catch (IOException e) {
    				log.error("圖片文件復制失敗!", e);
    			}
        	}
        	return IMAGES_TEMP_PATH;
        }
    /**
         * 獲取中文字體位置
         * @return
         */
        private String getChineseFont() {
    
            final InputStream stream = getClass().getClassLoader().getResourceAsStream("fonts/simsun.ttf");
            final File fileDir = new File("System.getProperty("user.dir") + "/fonts/"");
            if (!fileDir.exists()) {
                fileDir.mkdirs();
            }
            final String fontsPath = FONTS_TEMP_PATH + "simsun.ttf";
            final File targetFile = new File(fontsPath);
            try {
                FileUtils.copyInputStreamToFile(stream, targetFile);
            } catch (final IOException e) {
                log.error("字體文件復制失敗!", e);
            }
            return fontsPath;
        }

    還有一個問題至今沒有解決,就是關于生成PDF文件后自動換行的問題,參考了網上大多數的作法,都是修改模板樣式,生成的html確實是可以換行,但是對PDF無效。最后想出了一個比較笨也不是很合適的方法,在后臺先給它在某處先換好行,然后再生成PDF,雖然比較笨,也存在問題,但是確實解了燃眉之急。

    /**
         * 向字符串source中每隔sep個插入一個replace
         * @param source
         * @param sep
         * @param replace
         * @return
         */
        public String changeLine(final String source, final int sep, final String replace) {
        	if (source == null) {
    			return null;
    		}
        	final StringBuffer buffer = new StringBuffer(source);
    		for (int i = sep; i < source.length(); i+=(sep + 1)) {
    			buffer.insert(i, replace);
    		}
    		return buffer.toString();
    	}

    最終結果


    如果有大神知道如何正確實現自動換行,還請不吝賜教。

    版權聲明:本文為u012843873原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/u012843873/article/details/80581108

    智能推薦

    JavaWeb 利用 freemarker 根據模板生成word并下載

    1、用到的jar包 用到的jar包為freemarker-2.3.18.jar 2、word模板文件處理 首先將確定好的word模板文件另存為xml格式,用notepad++打開,將要替換的部分用${**}替換掉,如下圖所示: 如果有表格需要遍歷顯示的,找到對應需要遍歷的行,在外層用<#list ? as row ></#list>進行包圍,遍歷的行用 ${row.?}來替...

    使用FreeMarker生成模板代碼

    在平時開發過程中,一般都是需要Dao層,Service層,而每一層當中都需要自己編寫一部分常用代碼,例如在Dao(基于Mybatis框架)層中編寫返回值為List的方法用于查詢數據庫中數據,或者是add方法對數據庫執行插入操作等一系列的方法,而且我們發現再換做另外一張表的時候也是這種操作,list,add。。。。。。 那么什么樣的方式可以減少這種重復的工作呢? FreeMarker可以做到,Fre...

    freemarker自動生成代碼模板

    http://download.csdn.net/download/dwangc/9895462 最近需求中,根據數據庫表的信息生成PO,DAO,還有sql語句,如果手寫很是重復繁瑣。然后又要用到mybaties,所以給我的任務就是自動生成PO類,DAO類和sql的xml文件。 首先分析了給我的最簡單的需求樣例, 1. 一個實體類對應數據庫表的字段。 2. 一個DAO類,包括簡單的有null in...

    用freemarker生成word模板

    需求: 給文書統一生成一個搞頭文件,文件內容基本是一樣的。 用freemarker生成docx文檔 一、生成一個docx結尾的word模板,然后把文檔的后綴docx改成zip,zip里會有生成很多文件。如下圖: 然后打開word文件夾,如下圖: 把document.xml拿出來,把后綴xml改成ftl,然后把里面的內容(在線格式化xml)格式化一下,把一些可變的參數做成變量。 二、在resourc...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    猜你喜歡

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    精品国产乱码久久久久久蜜桃不卡