utils工具类:
public class WordUtils { private FTPClient ftp; public WordUtils() throws IOException { } /** * 替换段落里面的变量 * * @param para 要替换的段落 * @param params 参数 */ public static void replaceInPara(XWPFParagraph para, Map<String, String> params) { List<XWPFRun> runs; Matcher matcher; runs = para.getRuns(); for (int i = 0; i < runs.size(); i++) { XWPFRun run = runs.get(i); String runText = run.toString(); matcher = matcher(runText); String group; if (matcher.find()) { group = matcher.group(); } else { continue; } for (Map.Entry<String, String> entry : params.entrySet()) { if (group.equals(entry.getKey())) { String resultValue; if (StringUtils.isBlank(entry.getValue())) { resultValue = runText.replace(entry.getKey(), "无"); } else { resultValue = runText.replace(entry.getKey(), entry.getValue()); } para.removeRun(i); para.insertNewRun(i).setText(resultValue); } } } } /** * 导出docx文件,浏览器下载 * * @param params params * @param fileName fileName * @param inputStream inputStream * @param response response */ public void exportWord(Map<String, String> params, String fileName, InputStream inputStream, HttpServletResponse response) throws IOException { exportWord(params, fileName, inputStream, response, null, null, StringConstants.NUMBER_ZERO, null, null, null); } //导出docx文件,浏览器下载 public void exportWord(Map<String, String> params, String fileName, InputStream inputStream, HttpServletResponse response, List<DocumentPicturesEntity> doumentPicturesEntityList, String ftpUrl, int ftpPort, String ftpUsername, String ftpPassword, String fileDir) throws IOException { String encode = URLEncoder.encode(fileName, "utf-8"); XWPFTemplate template = XWPFTemplate.compile(inputStream); //替换表格里面的变量 XWPFDocument doc = template.getXWPFDocument(); replaceInTable(doc, params); // 处理图片,如果list里面有数据 if (CollUtil.isNotEmpty(doumentPicturesEntityList)) { // 加个try catch来吃了,避免因为图片导出失败,调试的时候报错多看看这里,有可能吃掉了 try { dealPicture(doc, doumentPicturesEntityList, ftpUrl, ftpPort, ftpUsername, ftpPassword, fileDir); } catch (InvalidFormatException e) { e.printStackTrace(); log.error("处理图片报错了", e.getMessage()); } } // 加密 doc.enforceReadonlyProtection(RandomUtil.randomString(10), HashAlgorithm.sha512); response.setContentType("application/msword"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); //设置浏览器以下载的方式处理该文件-下载文件名称乱码处理 response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + encode + ";" + "filename*=utf-8''" + encode); response.addHeader("filename", encode); ServletOutputStream os = null; try { os = response.getOutputStream(); doc.write(os); os.flush(); os.close(); } catch (Exception exception) { exception.printStackTrace(); } finally { if (os != null) { os.close( /** * 替换表格里面的变量 * * @param doc 要替换的文档 * @param params 参数 */ public static void replaceInTable(XWPFDocument doc, Map<String, String> params) { Iterator<XWPFTable> iterator = doc.getTablesIterator(); XWPFTable table; List<XWPFTableRow> rows; List<XWPFTableCell> cells; List<XWPFParagraph> paras; while (iterator.hasNext()) { table = iterator.next(); rows = table.getRows(); for (XWPFTableRow row : rows) { cells = row.getTableCells(); for (XWPFTableCell cell : cells) { paras = cell.getParagraphs(); for (XWPFParagraph para : paras) { replaceInPara(para, params); } } } } } /** * 正则匹配字符串 * * @param str * @return */ public static Matcher matcher(String str) { Pattern pattern = Pattern.compile("\\w+", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(str); return matcher; } /** * 关闭输入流 * * @param is */ public static void close(InputStream is) { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 关闭输出流 * * @param os */ public static void close(OutputStream os) { if (os != null) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 处理word中的图片 * * @param doc * @param doumentPicturesEntityList * @author zx * @date 2022/6/28 14:24 */ private void dealPicture(XWPFDocument doc, List<DocumentPicturesEntity> doumentPicturesEntityList, String ftpUrl, int ftpPort, String ftpUsername, String ftpPassword, String fileDir) throws IOException, InvalidFormatException { boolean connect = connect(ftpUrl, ftpPort, ftpUsername, ftpPassword); if (!connect) { return; } log.info("进入处理图片的方法"); log.info(doumentPicturesEntityList.toString()); // 循环处理图片,每一次循环是一个table的cell for (DocumentPicturesEntity doumentPicturesEntity : doumentPicturesEntityList) { XWPFParagraph xwpfParagraph = doc.getTables().get(0).getRow(doumentPicturesEntity.getRow()).getCell(doumentPicturesEntity.getCell()).getParagraphs().get(0); XWPFRun run = xwpfParagraph.createRun(); // 一个cell里面可能放多个图片,所以这里循环处理 for (Picture picture : doumentPicturesEntity.getPicturesUrls()) { // 判断下图片类型 int format = suggestFileType(picture.getFilePath()); log.info("图片类型:" + format); // 读取图片到输入流里 InputStream fis = readFile(picture, this.ftp); // 将图片加入进去 run.addPicture(fis, format, picture.getName(), Units.toEMU(picture.getWidth()), Units.toEMU(picture.getHeight())); fis.close(); // 多文件 boolean b = ftp.completePendingCommand(); System.out.println(b); } } ftp.logout(); ftp.disconnect(); } private InputStream readFile(Picture picture, FTPClient ftpClient) throws IOException { // 如果是本地存储方式 if (DefaultFile.SAVE_TYPE_FOLDER.equals(picture.getFileSaveType())) { // TODO } else if (DefaultFile.SAVE_TYPE_FTP.equals(picture.getFileSaveType())) { String replace = picture.getFilePath().replace("\\", "/"); String path = replace.substring(replace.indexOf("/"), replace.lastIndexOf("/")); log.info("path" + path); try { if (path != null && path.length() > 0) { // 跳转到指定目录 boolean b = ftpClient.changeWorkingDirectory(path); log.info("切换工作目录:" + b); InputStream inputStream = ftpClient.retrieveFileStream(picture.getFileId()); log.info("文件ID:" + picture.getFileId()); return inputStream; } } catch (SocketException e) { e.printStackTrace(); log.error("处理图片报错了2", e.getMessage()); } catch (IOException e) { e.printStackTrace(); log.error("处理图片报错了3", e.getMessage()); } } return null; } //链接ftp public boolean connect(String addr, int port, String username, String password) { ftp = new FTPClient(); try { ftp.connect(addr, port); ftp.login(username, password); // 被动模式 ftp.enterLocalPassiveMode(); ftp.setFileType(ftp.BINARY_FILE_TYPE); /* if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) { ftp.disconnect(); return false; }*/ return true; } catch (SocketException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } } private int suggestFileType(String imgFile) { int format = 0; if (imgFile.endsWith(".emf")) { format = XWPFDocument.PICTURE_TYPE_EMF; } else if (imgFile.endsWith(".wmf")) { format = XWPFDocument.PICTURE_TYPE_WMF; } else if (imgFile.endsWith(".pict")) { format = XWPFDocument.PICTURE_TYPE_PICT; } else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) { format = XWPFDocument.PICTURE_TYPE_JPEG; } else if (imgFile.endsWith(".png")) { format = XWPFDocument.PICTURE_TYPE_PNG; } else if (imgFile.endsWith(".dib")) { format = XWPFDocument.PICTURE_TYPE_DIB; } else if (imgFile.endsWith(".gif")) { format = XWPFDocument.PICTURE_TYPE_GIF; } else if (imgFile.endsWith(".tiff")) { format = XWPFDocument.PICTURE_TYPE_TIFF; } else if (imgFile.endsWith(".eps")) { format = XWPFDocument.PICTURE_TYPE_EPS; } else if (imgFile.endsWith(".bmp")) { format = XWPFDocument.PICTURE_TYPE_BMP; } else if (imgFile.endsWith(".wpg")) { format = XWPFDocument.PICTURE_TYPE_WPG; } else { log.error("Unsupported picture: " + imgFile + ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg"); } return format; } }
调用工具类实现:
// 替换文本数据构建 HashMap<String, String> insertTextMap = new HashMap<>(); insertTextMap.put("opinionFour", opinionFour);
//JAR包形式用的路径 String templatePath = "classpath:static\\public\\uploadTemplate\\故障报告导出模板.docx"; //获取模板 Resource resource = resourceLoader.getResource(templatePath); //获取图片信息 List<DocumentPicturesEntity> documentPicturesEntityList =getDocumentPicturesEntityList(faultFile); //生成word文档 WordUtils wordUtil = new WordUtils(); //insertTextMap-文本替换变量;fileName-生成的word名;inputStream-模板的io流;reponse-前端响应;documentPicturesEntityList-图片替换集合;ftpUrl, ftpPort, ftpUsername, ftpPassword,fileDir-需要连接的ftp配置及文件所在位置(通过连接ftp获取图片的文件流,写入word中) wordUtil.exportWord(insertTextMap, fileName, resource.getInputStream(), httpServletResponse, documentPicturesEntityList,ftpUrl, ftpPort, ftpUsername, ftpPassword, fileDir); //图片信息 private List<DocumentPicturesEntity> getDocumentPicturesEntityList(FaultFile file){ List<DocumentPicturesEntity> documentPicturesEntityList = new ArrayList<>(); for (Integer i = 0; i < defaultFiles.size(); i++) { List<Picture> pictureList = new ArrayList<>(); Picture picture = new Picture(); picture.setName("图片"); // 可以不填 picture.setFileId(defaultFile.getId()); picture.setFilePath(defaultFile.getFilePath()); picture.setFileSaveType(defaultFile.getStoreType()); pictureList.add(picture); documentPicturesEntity.setRow(9); // 图片所在行 documentPicturesEntity.setCell(1); // 图片所在列 documentPicturesEntity.setPicturesUrls(pictureList); documentPicturesEntityList.add(documentPicturesEntity); } }
//word模板中变量不需要加'${}'特殊字符来辨认;设置好指定图片所在区域