Java根据关键字在PDF/Word插入图片
生活随笔
收集整理的這篇文章主要介紹了
Java根据关键字在PDF/Word插入图片
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
該需求就是在pdf/word中,根據定義的關鍵字標識,進行插入圖片。不多說直接上代碼。
工具類都是參照網上的進行小改一番
PDF根據關鍵字插入圖片
1、引入依賴
<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.6</version> </dependency>2、插入圖片工具類
import java.awt.*; import java.io.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;import antlr.ANTLRError; import com.itextpdf.awt.geom.Rectangle2D; import com.itextpdf.text.BadElementException; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Image; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; import com.itextpdf.text.pdf.parser.ImageRenderInfo; import com.itextpdf.text.pdf.parser.PdfReaderContentParser; import com.itextpdf.text.pdf.parser.RenderListener; import com.itextpdf.text.pdf.parser.TextRenderInfo; import com.landray.elasticsearch.rest.error.Error; import com.landray.kmss.sys.log.util.F;public class PDFUtil_img {/*** filepath:文件路徑加文件名* KEY_WORD:關鍵字 要求:(報表中關鍵字不能加粗,宋體,字號9)* 編輯PDF可使用迅捷PDF編輯器*/public static Map<String, Object> getKeyWords(String filePath, final List<String> keyWords) {final Map<String, Object> result = new HashMap<String, Object>();try {PdfReader pdfReader = new PdfReader(filePath);//獲取PDF的頁數int pageNum = pdfReader.getNumberOfPages();PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);for (int i = 1; i <= pageNum; i++) {final int currIndex = i;pdfReaderContentParser.processContent(currIndex, new RenderListener() {@Overridepublic void renderText(TextRenderInfo textRenderInfo) {String text = textRenderInfo.getText(); // 整頁內容if (null != text && keyWords.contains(text)) {Rectangle2D.Float boundingRectange = textRenderInfo.getBaseline().getBoundingRectange();List<Map<String, Object>> locationList = (List<Map<String, Object>>) result.get(text);if (locationList == null) {locationList = new ArrayList<Map<String, Object>>();result.put(text, locationList);}Map<String, Object> location = new HashMap<String, Object>();location.put("x", boundingRectange.x);location.put("y", boundingRectange.y);location.put("width", boundingRectange.width);location.put("height", boundingRectange.height);location.put("pageNo", currIndex);locationList.add(location);}}@Overridepublic void renderImage(ImageRenderInfo arg0) {}@Overridepublic void endTextBlock() {}@Overridepublic void beginTextBlock() {}});}pdfReader.close();} catch (IOException e) {e.printStackTrace();}return result;}public static void addImg(PdfStamper stamper, Map<String, Object> location, String imagePath) {for (int i = 0; i < 1; i++) {Image image = null;try {image = Image.getInstance(imagePath, false);float imgWidth = image.getWidth() * 0.05f + 3;float imgHeight = image.getHeight() * 0.05f - 3;PdfContentByte pdfContentByte = stamper.getOverContent((int) location.get("pageNo"));//設置圖片大小image.scaleAbsolute(imgWidth, imgHeight);//設置圖片位置image.setAbsolutePosition((Float) location.get("x"), (Float) location.get("y") - 4);// X Y的位置System.out.println("x:" + (Float) location.get("x"));System.out.println("y:" + ((Float) location.get("y") - 4));pdfContentByte.addImage(image);System.out.println("插入成功");} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) throws Exception {//模板的路徑String templatePath = "D:\\用戶\\***.pdf";//生成的新文件路徑String newPDFPath = "D:\\用戶\\***_update.pdf";//解析文件PdfReader reader = new PdfReader(templatePath);FileOutputStream fOut = new FileOutputStream(newPDFPath);PdfStamper stamper = new PdfStamper(reader, fOut);//關鍵字集合List<String> keyWords = new ArrayList<>();keyWords.add("$sign$");keyWords.add("$sh$");keyWords.add("$gy$");Map<String, Object> result = getKeyWords(templatePath, keyWords);System.out.println(result);for (Map.Entry<String, Object> entry : result.entrySet()) {String key = entry.getKey();List<Map<String, Object>> locationList = (List<Map<String, Object>>) entry.getValue();if (!locationList.isEmpty()) {addImg(stamper, locationList.get(0), "D:\\用戶\\sign.png");//圖片路徑}}//設置不可編輯stamper.setFormFlattening(true);stamper.close();// 將輸出流關閉fOut.close();reader.close();}//拷貝文件的方法(根據自身需求選擇)private static void copyFileUsingStream(File file, File newFile) throws IOException {InputStream is = null;OutputStream os = null;try {is = new FileInputStream(file);os = new FileOutputStream(newFile);byte[] buffer = new byte[1024];int length;while ((length = is.read(buffer)) > 0) {os.write(buffer, 0, length);}} finally {if (is != null)is.close();if (os != null)os.close();}}/*** @param tmp 臨時文件路徑* @param PDFPath PDF全路徑* @param keyWords 關鍵字* @param imagePath 圖片路徑* @throws Exception*/ //該方法是插入圖片且文件名不變,從而實現"原文件"上進行插入。(根據自身需求選擇)public static void pdfover(String tmp, String PDFPath, List<String> keyWords, String imagePath) throws Exception {File file = new File(PDFPath);File tempFile = null;//過濾不合規路徑名String tempPath = tmp.replaceAll("[^\\u4e00-\\u9fa5\\u4e00-\\u9fa5a-zA-Z0-9~!@#$%^&( )_\\-{}’]", "");if (file != null && file.exists()) {copyFileUsingStream(file, new File(tempPath));file.delete();PdfReader reader = new PdfReader(tempPath);FileOutputStream fOut = new FileOutputStream(PDFPath);PdfStamper stamper = new PdfStamper(reader, fOut);Map<String, Object> result = getKeyWords(tempPath, keyWords);if (result.size() > 0) {for (Map.Entry<String, Object> entry : result.entrySet()) {String key = entry.getKey();List<Map<String, Object>> locationList = (List<Map<String, Object>>) entry.getValue();if (!locationList.isEmpty()) {for (int i = 0; i < locationList.size(); i++) {addImg(stamper, locationList.get(i), imagePath);}}}}if (result.size() == 0) {copyFileUsingStream(new File(tempPath), new File(PDFPath));}//設置不可編輯stamper.setFormFlattening(true);stamper.close();// 將輸出流關閉fOut.close();reader.close();//刪除臨時文件tempFile = new File(tempPath);if (tempFile.exists()) {tempFile.delete();}}} }注意:
1、PDF設置關鍵字時,轉Word設置再轉PDF是無法正確識別關鍵字,這邊建議比較好用的PDF編輯器:迅捷PDF編輯器。
2、pdfover和copyFileUsingStream方法自行選擇,用不到可以自行刪除。
3、代碼有的考慮的不是很全,各位大佬可以自行優化。
Word根據關鍵字插入圖片
Word插入我這有兩種,可自行選擇,都是從網上搜索然后小改
1、方式一
1.1、導入依賴
<!--注意:word中要使用循環等標簽必須單獨導入以下依賴--> <dependency><groupId>org.apache.poi</groupId><artifactId>ooxml-schemas</artifactId><version>1.4</version> </dependency> <!-- word導出 方式:easypoi--> <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.3.0</version> </dependency> <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-web</artifactId><version>4.3.0</version> </dependency>1.2、工具類
import java.io.*; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map;import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import cn.afterturn.easypoi.entity.ImageEntity; import cn.afterturn.easypoi.word.entity.MyXWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.springframework.util.Assert;import cn.afterturn.easypoi.word.WordExportUtil; import org.springframework.web.multipart.MultipartFile;public class WordUtil {/*** 生成Word** @param map* @param outputStream* @return*/public static boolean PoiDown(Map<String, Object> map, OutputStream outputStream) {//導入模板XWPFDocument xwpfDocument = null;try {xwpfDocument = WordExportUtil.exportWord07("templates/template.docx", map);//使用流寫出xwpfDocument.write(outputStream);//刷新關閉流outputStream.flush();outputStream.close();System.out.println("work is over !");} catch (Exception exception) {exception.printStackTrace();return false;}return true;}/*** 根據用戶模板替換 {{photo}} 圖片* @param word* @param map* @param outputStream* @return*/public static boolean WordPhoto( XWPFDocument word, Map<String, Object> map, OutputStream outputStream) {try {WordExportUtil.exportWord07(word, map);//使用流寫出word.write(outputStream);outputStream.flush();outputStream.close();System.out.println("work is over !");} catch (Exception exception) {exception.printStackTrace();return false;}return true;}/*** 導出word* <p>第一步生成替換后的word文件,只支持docx</p>* <p>第二步下載生成的文件</p>* <p>第三步刪除生成的臨時文件</p>* 模版變量中變量格式:{{foo}}** @param is word模板文件流* @param temDir 生成臨時文件存放地址* @param fileName 文件名* @param params 替換的參數* @param request HttpServletRequest* @param response HttpServletResponse*/public static void exportWord(InputStream is, String temDir, String fileName, Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {Assert.notNull(is, "模板不能為空");Assert.notNull(temDir, "臨時文件路徑不能為空 ");Assert.notNull(fileName, "導出文件名不能為空 ");Assert.isTrue(fileName.endsWith(".docx"), "word導出請使用docx格式");if (!temDir.endsWith("/")) {temDir = temDir + File.separator;}File dir = new File(temDir);if (!dir.exists()) {dir.mkdirs();}try {String userAgent = request.getHeader("user-agent").toLowerCase();if (userAgent.contains("msie") || userAgent.contains("like gecko")) {fileName = URLEncoder.encode(fileName, "UTF-8");} else {fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");}MyXWPFDocument doc = new MyXWPFDocument(is);WordExportUtil.exportWord07(doc, params);String tmpPath = temDir + fileName;FileOutputStream fos = new FileOutputStream(tmpPath);doc.write(fos);// 設置強制下載不打開response.setContentType("application/force-download");// 設置文件名response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);OutputStream out = response.getOutputStream();doc.write(out);out.close();} catch (Exception e) {e.printStackTrace();} finally {delFileWord(temDir, fileName);//這一步看具體需求,要不要刪}}/*** 刪除零時生成的文件*/public static void delFileWord(String filePath, String fileName) {File file = new File(filePath + fileName);File file1 = new File(filePath);file.delete();file1.delete();}public static void main(String[] args) throws Exception {//存放關鍵字映射的數據// key:word中的關鍵字 value:映射的數據Map<String,Object> map = new HashMap();//存放基本數據map.put("name","張三");map.put("sex","男");map.put("mz","漢族");//存放照片ImageEntity img = new ImageEntity();img.setHeight(100);//高img.setWidth(130);//寬//圖片路徑、類型img.setUrl("圖片路徑\\Saved Pictures\\avatar.jpg");img.setType(ImageEntity.URL);map.put("photo",img);//導入模板,模板中是寫有關鍵字的XWPFDocument xwpfDocument = WordExportUtil.exportWord07("模板路徑\\template.docx", map);//使用流寫出到OutputStream os = new FileOutputStream("生成路徑\\test.docx");xwpfDocument.write(os);//刷新關閉流os.flush();os.close();System.out.println("work is over !");} }2、方式二
2.1、引入依賴
<dependency><groupId>net.sf.jacob-project</groupId><artifactId>jacob</artifactId><version>1.14.3</version> </dependency>2.2、工具類
package com.landray.kmss.lszn.knowledge.util;import java.io.*; import java.util.ArrayList; import java.util.List;import com.jacob.activeX.ActiveXComponent; import com.jacob.com.Dispatch; import com.jacob.com.Variant; import com.landray.kmss.sys.log.util.F;public class WordUtil_img {// word運行程序對象private ActiveXComponent word;// 所有word文檔集合private Dispatch documents;// word文檔private Dispatch doc;// 選定的范圍或插入點private Dispatch selection;// 保存退出private boolean saveOnExit;/*** 是否可見word程序* @param visible true-可見word程序,false-后臺默默執行。*/public WordUtil_img(boolean visible) {word = new ActiveXComponent("Word.Application");word.setProperty("Visible", new Variant(visible));documents = word.getProperty("Documents").toDispatch();}/*** 打開一個已經存在的Word文檔* @param docPath 文件的路徑*/public void openDocument(String docPath) {doc = Dispatch.call(documents, "Open", docPath).toDispatch();selection = Dispatch.get(word, "Selection").toDispatch();}/*** 全局將指定的文本替換成圖片* @param findText* @param imagePath*/public void replaceAllImage(String findText, String imagePath, int width, int height){moveStart();while (find(findText)){Dispatch picture = Dispatch.call(Dispatch.get(getSelection(), "InLineShapes").toDispatch(), "AddPicture", imagePath).toDispatch();Dispatch.call(picture, "Select");Dispatch.put(picture, "Width", new Variant(width));Dispatch.put(picture, "Height", new Variant(height));moveStart();}}/*** 把插入點移動到文件首位置*/public void moveStart(){Dispatch.call(getSelection(), "HomeKey", new Variant(6));}/*** 獲取當前的選定的內容或者插入點* @return 當前的選定的內容或者插入點*/public Dispatch getSelection(){if (selection == null)selection = Dispatch.get(word, "Selection").toDispatch();return selection;}/*** 從選定內容或插入點開始查找文本* @param findText 要查找的文本* @return boolean true-查找到并選中該文本,false-未查找到文本*/public boolean find(String findText){if(findText == null || findText.equals("")){return false;}// 從selection所在位置開始查詢Dispatch find = Dispatch.call(getSelection(), "Find").toDispatch();// 設置要查找的內容Dispatch.put(find, "Text", findText);// 向前查找Dispatch.put(find, "Forward", "True");// 設置格式Dispatch.put(find, "Format", "True");// 大小寫匹配Dispatch.put(find, "MatchCase", "True");// 全字匹配Dispatch.put(find, "MatchWholeWord", "True");// 查找并選中return Dispatch.call(find, "Execute").getBoolean();}/*** 文檔另存為* @param savePath*/public void saveAs(String savePath){Dispatch.call(doc, "SaveAs", savePath);}/*** 關閉word文檔*/public void closeDocument(){if (doc != null) {Dispatch.call(doc, "Close", new Variant(saveOnExit));doc = null;}}/*** * @param WordPath 讀取的word路徑* @param ImgPaht 圖片路徑* @param keyWord 關鍵字集合* @param NewPath 生成的word路徑*/public static void WordInsertImg(String WordPath, String ImgPaht, List<String> keyWord,String NewPath) throws IOException {WordUtil_img demo = new WordUtil_img(false);//獲取工具類對象demo.openDocument(WordPath);//打開word// 在指定位置插入指定的圖片for (String key : keyWord) {demo.replaceAllImage(key,ImgPaht,100,50);//圖片位置。長和寬。demo.saveAs(NewPath);//插入成功后生成的新word.doc/docx,//注意:生成的Word會帶doc/docx后綴。demo.closeDocument();//關閉對象。System.out.println("插入成功");}}public static void main(String[] args) throws IOException {//關鍵字集合List<String> keyword = new ArrayList<>();keyword.add("$sign$");WordInsertImg("讀取的word路徑","插入的圖片路徑",keyword,"生成的word路徑");}}來源: 半末の博客
總結
以上是生活随笔為你收集整理的Java根据关键字在PDF/Word插入图片的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 1727 Hastiness(模
- 下一篇: java美元兑换,(Java实现) 美元