• 公司HDFS网盘下载word模板,实现对模板的数据填充和创建临时文件上传


     1  /**
     2      * 获取通报单模板,填充模板,并上传网盘返回fileId
     3      */
     4     private JSONObject getReport(String reportNo, String projectName, String notificationObject, String notificationReason, HttpServletRequest request) {
     5         JSONObject returnJson = new JSONObject();
     6 
     7         RestTemplate restTemplate = new RestTemplate();
     8         HttpHeaders httpHeaders = new HttpHeaders();
     9         HttpEntity httpEntity = new HttpEntity(httpHeaders);
    10         InputStream in = null;
    11         ByteArrayOutputStream out = new ByteArrayOutputStream();
    12         //填充模板的数据
    13         JSONObject params = new JSONObject();
    14         JSONObject tableData = new JSONObject();
    15         tableData.put("number", reportNo);
    16         tableData.put("date", DateUtil.format(new Date(), "yyyy-MM-dd").toString());
    17         tableData.put("title", projectName);
    18         tableData.put("target", notificationObject);
    19         tableData.put("reason", notificationReason);
    20         params.put("tableData", tableData);
    21 
    22         String fileId = null;
    23         FileOutputStream fos = null;
    24         BufferedOutputStream bos = null;
    25         File fi = null;
    26         try {
    27             ResponseEntity<byte[]> getTempResponse = restTemplate.exchange(netdiscIP + netdiscDownload + reportTempFileId, HttpMethod.GET, httpEntity, byte[].class);
    28             ByteArrayInputStream inputStream = new ByteArrayInputStream(getTempResponse.getBody());
    29             PoiWordUtils.execute(inputStream, out, params);
    30             byte[] bytes = out.toByteArray();
    31             HttpHeaders headers = new HttpHeaders();
    32             //设置名字
    33             String downloadName = "督查通报建议单.docx";
    34             //解决chrome/firefox/ie浏览器压缩包名字含有中文时乱码的问题
    35             String agent = request.getHeader("USER-AGENT");
    36             if (agent.contains("MSIE") || agent.contains("Trident")) {
    37                 downloadName = java.net.URLEncoder.encode(downloadName, StandardCharsets.UTF_8.toString());
    38             } else {
    39                 downloadName = new String(downloadName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
    40             }
    41             headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;fileName="" + downloadName + """);
    42             headers.add(HttpHeaders.CONNECTION, "close");
    43 
    44             //创建临时文件上传
    45             String tempFileName = "督查通报建议单_" + System.currentTimeMillis();
    46             fi = File.createTempFile(tempFileName, ".docx");
    47             fos = new FileOutputStream(fi);
    48             bos = new BufferedOutputStream(fos);
    49             bos.write(bytes);
    50 
    51             //设置请求头
    52             HttpHeaders requestHeaders = new HttpHeaders();
    53             MediaType type = MediaType.parseMediaType("multipart/form-data");
    54             requestHeaders.setContentType(type);
    55             System.out.println(fi);
    56             System.out.println(fi.getName());
    57 
    58             //设置请求体,注意是LinkedMultiValueMap
    59             FileInputStream input = new FileInputStream(fi);
    60             MultipartFile multipartFile = new MockMultipartFile("file", fi.getName(), "text/plain", IOUtils.toByteArray(input));
    61             HttpClientResult result = HttpClientUtils.doPostFile(netdiscIP + netdiscUpload, multipartFile);
    62             JSONObject object = JSONObject.parseObject(result.getContent());
    63             if (object != null && object.getInteger("code") == 200) {
    64                 fileId = object.getString("data");
    65             }
    66             returnJson.put("fileName",tempFileName + ".docx");
    67             returnJson.put("fileId",fileId );
    68         } catch (Exception e) {
    69             throw new RuntimeException(e.getMessage());
    70         } finally {
    71             try {
    72                 if (bos != null) {
    73                     try {
    74                         bos.close();
    75                     } catch (IOException e1) {
    76                         e1.printStackTrace();
    77                     }
    78                 }
    79                 if (fos != null) {
    80                     try {
    81                         fos.close();
    82                     } catch (IOException e1) {
    83                         e1.printStackTrace();
    84                     }
    85                 }
    86                 if (in != null) {
    87                     in.close();
    88                 }
    89                 fi.delete();
    90                 out.close();
    91             } catch (IOException e) {
    92                 throw new RuntimeException(e.getMessage());
    93             }
    94         }
    95         return returnJson;
    96     }
    PoiWordUtils:
      1 @Slf4j
      2 public class PoiWordUtils {
      3 
      4     /**
      5      * 顿号
      6      */
      7     private static final String DUNHAO = "、";
      8 
      9     /**
     10      * 执行
     11      *
     12      * @param in     模板输入流
     13      * @param out    文件输出流
     14      * @param params params
     15      * @Author LIZHIQIANG
     16      * @Date Create in 2020/1/14 9:58
     17      */
     18     public static void execute(InputStream in, OutputStream out, JSONObject params) {
     19         try {
     20             XWPFDocument document = new XWPFDocument(in);
     21             //需要循环的段落${listRow}开头,暂定最多三个
     22             List<XWPFParagraph> targetParagraphs1 = new ArrayList<>();
     23             List<XWPFParagraph> targetParagraphs2 = new ArrayList<>();
     24             List<XWPFParagraph> targetParagraphs3 = new ArrayList<>();
     25             List<IBodyElement> bodyElements = document.getBodyElements();
     26             for (IBodyElement element : bodyElements) {
     27                 //文本段落对象
     28                 if (element instanceof XWPFParagraph) {
     29                     XWPFParagraph paragraph = (XWPFParagraph) element;
     30                     //段落内容
     31                     String paragraphText = paragraph.getParagraphText();
     32 
     33                     //空段落跳过
     34                     if (paragraphText.isEmpty()) {
     35                         continue;
     36                     }
     37                     //需要循环的段落
     38                     if (paragraphText.startsWith("${listRow1}")) {
     39                         targetParagraphs1.add(paragraph);
     40                         continue;
     41                     }
     42                     if (paragraphText.startsWith("${listRow2}")) {
     43                         targetParagraphs2.add(paragraph);
     44                         continue;
     45                     }
     46                     if (paragraphText.startsWith("${listRow3}")) {
     47                         targetParagraphs3.add(paragraph);
     48                         continue;
     49                     }
     50                     //处理普通段落
     51                     processParagraph(paragraph, params);
     52                 } else if (element instanceof XWPFTable) {
     53                     XWPFTable table = (XWPFTable) element;
     54                     List<XWPFTableRow> rows = table.getRows();
     55                     String tableDataString = params.getString("tableData");
     56                     JSONObject tableData = JSON.parseObject(tableDataString);
     57                     System.out.println(JSON.toJSONString(tableData,true));
     58                     if (tableData == null) {
     59                         continue;
     60                     }
     61                     //需要循环的tableRows
     62                     List<XWPFTableRow> targetTableRows = new ArrayList<>();
     63                     List<Integer> targetTableRowsPos = new ArrayList<>();
     64                     for (int i = 0; i < rows.size(); i++) {
     65                         XWPFTableRow row = rows.get(i);
     66                         List<XWPFTableCell> cells = row.getTableCells();
     67                         String firstParagraphText2 = cells.get(0).getParagraphs().get(0).getParagraphText();
     68                         String firstParagraphText = cells.get(0).getParagraphs().get(0).getText();
     69                         if (firstParagraphText.startsWith("${listTables")) {
     70                             targetTableRows.add(row);
     71                             targetTableRowsPos.add(i);
     72                             continue;
     73                         }
     74                         for (XWPFTableCell cell : cells) {
     75                             List<XWPFParagraph> paragraphs = cell.getParagraphs();
     76                             for (XWPFParagraph paragraph : paragraphs) {
     77                                 processParagraph(paragraph, tableData);
     78                             }
     79                         }
     80                     }
     81                     processTableRows(table, targetTableRows, targetTableRowsPos, tableData);
     82                 }
     83 
     84             }
     85             //处理循环段落
     86             processParagraphs(document, targetParagraphs1, params, "1");
     87             processParagraphs(document, targetParagraphs2, params, "2");
     88             processParagraphs(document, targetParagraphs3, params, "3");
     89             document.write(out);
     90 
     91         } catch (IOException e) {
     92             e.printStackTrace();
     93         }
     94     }
     95 
     96     /**
     97      * 处理普通段落
     98      *
     99      * @param paragraph paragraph
    100      * @param params    params
    101      * @Author LIZHIQIANG
    102      * @Date Create in 2020/1/14 9:38
    103      */
    104     private static void processParagraph(XWPFParagraph paragraph, JSONObject params) {
    105 
    106         List<XWPFRun> runs = paragraph.getRuns();
    107         //需要循环替换的单元
    108         List<XWPFRun> targetRuns1 = new ArrayList<>();
    109         List<XWPFRun> targetRuns2 = new ArrayList<>();
    110         List<XWPFRun> targetRuns3 = new ArrayList<>();
    111         for (XWPFRun run : runs) {
    112             String runKey = run.text();
    113             System.out.println(runKey);
    114             if (!runKey.startsWith("${") || !runKey.endsWith("}")) {
    115                 continue;
    116             }
    117             if ("${#}".equals(runKey)) {
    118                 run.setText("", 0);
    119                 continue;
    120             }
    121             if ("${listTables1}".equals(runKey)) {
    122                 run.setText("", 0);
    123                 continue;
    124             }
    125             if (runKey.startsWith("${listRow")) {
    126                 run.setText("", 0);
    127                 continue;
    128             }
    129             //添加需要循环的单元
    130             if (runKey.startsWith("${listRuns1")) {
    131                 targetRuns1.add(run);
    132                 continue;
    133             }
    134             if (runKey.startsWith("${listRuns2")) {
    135                 targetRuns2.add(run);
    136                 continue;
    137             }
    138             if (runKey.startsWith("${listRuns3")) {
    139                 targetRuns3.add(run);
    140                 continue;
    141             }
    142             String key = runKey.replace("${", "").replace("}", "");
    143             String value = params.getString(key);
    144             if (!StringUtils.isEmpty(value)) {
    145                 run.setText(value, 0);
    146             } else {
    147                 run.setText("", 0);
    148                 log.warn("处理普通段落单元失败:{},找不到替换数据", runKey);
    149             }
    150         }
    151         //处理需要循环的单元
    152         processRuns(paragraph, targetRuns1, params, "1");
    153         processRuns(paragraph, targetRuns2, params, "2");
    154         processRuns(paragraph, targetRuns3, params, "3");
    155     }
    156 
    157     /**
    158      * 处理需要循环的单元
    159      *
    160      * @param paragraph  paragraph
    161      * @param targetRuns targetRuns
    162      * @param params     params
    163      * @return void
    164      * @Author LIZHIQIANG
    165      * @Date Create in 2020/3/1 18:06
    166      */
    167     private static void processRuns(XWPFParagraph paragraph, List<XWPFRun> targetRuns, JSONObject params, String sorting) {
    168 
    169         if (targetRuns.isEmpty() || params.isEmpty()) {
    170             return;
    171         }
    172         //默认key
    173         String defaultKey = "listRuns" + sorting;
    174         JSONArray jsonArray = params.getJSONArray(defaultKey);
    175         //循环需要替换的数据
    176         for (int i = 0; i < jsonArray.size(); i++) {
    177             Object data = jsonArray.get(i);
    178             //参数 一次循环的参数
    179             JSONObject param = JSON.parseObject(data.toString());
    180             //循环需要替换的单元
    181             for (XWPFRun run : targetRuns) {
    182 
    183                 String runKey = run.text();
    184                 XWPFRun newRun = paragraph.createRun();
    185                 CTRPr rPr = run.getCTR().getRPr();
    186                 newRun.getCTR().setRPr(rPr);
    187                 //处理顿号
    188                 if (runKey.equals("${" + defaultKey + "DUNHAO}")) {
    189                     if (i == jsonArray.size() - 1) {
    190                         newRun.setText("", 0);
    191                         continue;
    192                     }
    193                     newRun.setText(DUNHAO);
    194                     continue;
    195                 }
    196                 String key = runKey.replace("${", "").replace("}", "");
    197                 String value = param.getString(key);
    198                 if (!StringUtils.isEmpty(value)) {
    199                     newRun.setText(value);
    200                 } else {
    201                     log.warn("处理循环单元失败:{},找不到对应值", runKey);
    202                     newRun.setText("", 0);
    203                 }
    204 
    205             }
    206         }
    207         for (XWPFRun run : targetRuns) {
    208             run.setText("", 0);
    209         }
    210 
    211     }
    212 
    213     /**
    214      * 处理循环段落(新增段落后删模板段落)
    215      *
    216      * @param document         document
    217      * @param targetParagraphs targetParagraphs
    218      * @param params           params
    219      * @Author LIZHIQIANG
    220      * @Date Create in 2020/1/14 9:38
    221      */
    222     private static void processParagraphs(XWPFDocument document, List<XWPFParagraph> targetParagraphs, JSONObject params, String sorting) {
    223 
    224         if (targetParagraphs.isEmpty() || params.isEmpty()) {
    225             return;
    226         }
    227         String listKey = "listRow" + sorting;
    228         JSONArray jsonArray = params.getJSONArray(listKey);
    229         if (jsonArray == null) {
    230             return;
    231         }
    232 
    233         //document.insertNewParagraph(cursor) 插到这个光标前面 所以反转
    234         Collections.reverse(targetParagraphs);
    235         Collections.reverse(jsonArray);
    236         //需要追加的此段落后 最后一个
    237         XWPFParagraph lastParagraph = document.getParagraphArray(document.getPosOfParagraph(targetParagraphs.get(0)));
    238         //循环需要替换的数据
    239 //        for (int i = 0; i < jsonArray.size(); i++) {
    240 //            Object data = jsonArray.get(i);
    241 //            //参数 一次循环的参数
    242 //            JSONObject param = JSON.parseObject(data.toString());
    243 //            System.out.println(JSON.toJSONString(param,true));
    244 //            for (XWPFParagraph paragraph : targetParagraphs) {
    245 //                System.out.println("处理段落:"+paragraph.getText());
    246 //                //根据光标插入段落
    247 //                //需要追加的此段落光标后 最后一个
    248 //                XmlCursor cursor = lastParagraph.getCTP().newCursor();
    249 //                XWPFParagraph newPar = document.insertNewParagraph(cursor);
    250 //
    251 //                lastParagraph = newPar;
    252 //                //重置光标 最后插入的光标是这个
    253 //                //获取段落对象的样式的ppr标签
    254 //                CTPPr pPr = paragraph.getCTP().getPPr();
    255 //                newPar.getCTP().setPPr(pPr);
    256 //                List<XWPFRun> runs = paragraph.getRuns();
    257 //
    258 //                //需要循环替换的单元
    259 //                List<XWPFRun> targetRuns1 = new ArrayList<>();
    260 //                List<XWPFRun> targetRuns2 = new ArrayList<>();
    261 //                List<XWPFRun> targetRuns3 = new ArrayList<>();
    262 //                for (XWPFRun run : runs) {
    263 //                    String runKey = run.text();
    264 //                    CTRPr rPr = run.getCTR().getRPr();
    265 //                    XWPFRun newRun = newPar.createRun();
    266 //                    newRun.getCTR().setRPr(rPr);
    267 //                    if (!runKey.startsWith("${") || !runKey.endsWith("}")) {
    268 //                        newRun.setText(runKey);
    269 //                        continue;
    270 //                    }
    271 //                    //添加需要循环的单元
    272 //                    if (runKey.startsWith("${listRuns1")) {
    273 //                        targetRuns1.add(run);
    274 //                        continue;
    275 //                    }
    276 //                    if (runKey.startsWith("${listRuns2")) {
    277 //                        targetRuns2.add(run);
    278 //                        continue;
    279 //                    }
    280 //                    if (runKey.startsWith("${listRuns3")) {
    281 //                        targetRuns3.add(run);
    282 //                        continue;
    283 //                    }
    284 //                    if (("${" + listKey + "}").equals(runKey)) {
    285 //                        newRun.setText("");
    286 //                        continue;
    287 //                    }
    288 //                    if ("${#}".equals(runKey)) {
    289 //                        run.setText("", 0);
    290 //                        continue;
    291 //                    }
    292 //                    String key = runKey.replace("${", "").replace("}", "");
    293 //                    String value = param.getString(key);
    294 //                    if (!StringUtils.isEmpty(value)) {
    295 //                        newRun.setText(value);
    296 ////                        System.out.println("处理单元:"+runKey+" > "+value);
    297 //                        continue;
    298 //                    } else {
    299 //                        log.warn("处理循环模板段落单元失败:{},找不到对应值", runKey);
    300 //                    }
    301 //                    newRun.setText(runKey);
    302 //                }
    303 //                //===处理需要循环的单元
    304 //                processRuns(newPar, targetRuns1, param, "1");
    305 //                processRuns(newPar, targetRuns2, param, "2");
    306 //                processRuns(newPar, targetRuns3, param, "3");
    307 //
    308 //            }
    309 //        }
    310         //删除模板集合段落
    311         XmlCursor lastCursor = lastParagraph.getCTP().newCursor();
    312         for (Object data : jsonArray) {
    313             JSONObject param = JSON.parseObject(data.toString());
    314             for (XWPFParagraph paragraph : targetParagraphs) {
    315                 //根据光标插入段落
    316                 XWPFParagraph newPar = document.insertNewParagraph(lastCursor);
    317                 //重置光标 最后插入的光标是这个
    318                 lastCursor = newPar.getCTP().newCursor();
    319                 //复制段落
    320                 copyParagraph(paragraph, newPar);
    321                 //处理普通段落
    322                 processParagraph(newPar, param);
    323             }
    324         }
    325         for (XWPFParagraph paragraph : targetParagraphs) {
    326             document.removeBodyElement(document.getPosOfParagraph(paragraph));
    327         }
    328     }
    329 
    330     /**
    331      * 处理循环的表格行
    332      *
    333      * @param table              table
    334      * @param targetTableRows    targetTableRows
    335      * @param targetTableRowsPos targetTableRowsPos
    336      * @param params             params
    337      * @return void
    338      * @Author LIZHIQIANG
    339      * @Date Create in 2020/3/5 20:56
    340      */
    341     private static void processTableRows(XWPFTable table, List<XWPFTableRow> targetTableRows, List<Integer> targetTableRowsPos, JSONObject params) {
    342         if (targetTableRows.isEmpty() || params.isEmpty()) {
    343             return;
    344         }
    345         //默认key
    346         String defaultKey = "listTables1";
    347         JSONArray jsonArray = params.getJSONArray(defaultKey);
    348         if (jsonArray == null) {
    349             return;
    350         }
    351 
    352         for (int i = 0; i < targetTableRows.size(); i++) {
    353             XWPFTableRow row = targetTableRows.get(i);
    354             //循环需要替换的数据
    355             for (Object data : jsonArray) {
    356                 //参数 一次循环的参数
    357                 JSONObject param = JSON.parseObject(data.toString());
    358                 XWPFTableRow newRow = table.createRow();
    359                 copyTableRow(row, newRow);
    360                 List<XWPFTableCell> newRowCells = newRow.getTableCells();
    361                 for (XWPFTableCell newRowCell : newRowCells) {
    362                     List<XWPFParagraph> paragraphs = newRowCell.getParagraphs();
    363                     for (XWPFParagraph paragraph : paragraphs) {
    364                         processParagraph(paragraph, param);
    365                     }
    366                 }
    367             }
    368             table.removeRow(targetTableRowsPos.get(i));
    369         }
    370     }
    371 
    372 
    373     /**
    374      * 复制单元
    375      *
    376      * @param target target
    377      * @param source source
    378      */
    379     private static void copyRun(XWPFRun source, XWPFRun target) {
    380         // 设置run属性
    381         target.getCTR().setRPr(source.getCTR().getRPr());
    382         // 设置文本
    383         target.setText(source.text());
    384     }
    385 
    386     /**
    387      * 复制段落
    388      *
    389      * @param source 源段落
    390      * @param target 目标段落
    391      */
    392     private static void copyParagraph(XWPFParagraph source, XWPFParagraph target) {
    393         // 设置run属性
    394         target.getCTP().setPPr(source.getCTP().getPPr());
    395         //清除新段落的单元
    396         List<XWPFRun> targetRuns = target.getRuns();
    397         if (targetRuns != null && targetRuns.size() > 0) {
    398             for (int pos = 0; pos < targetRuns.size(); pos++) {
    399                 target.removeRun(pos);
    400             }
    401         }
    402         //复制源段落的单元到目标段落
    403         for (XWPFRun sourceRun : source.getRuns()) {
    404             XWPFRun targetRun = target.createRun();
    405             copyRun(sourceRun, targetRun);
    406         }
    407     }
    408 
    409     /**
    410      * 复制表格列
    411      *
    412      * @param source 源
    413      * @param target 目标
    414      */
    415     private static void copyTableCell(XWPFTableCell source, XWPFTableCell target) {
    416         // 设置TableCell属性
    417         target.getCTTc().setTcPr(source.getCTTc().getTcPr());
    418 
    419         List<XWPFParagraph> targetParagraphs = target.getParagraphs();
    420         if (targetParagraphs != null && targetParagraphs.size() > 0) {
    421             for (int pos = 0; pos < targetParagraphs.size(); pos++) {
    422                 target.removeParagraph(pos);
    423             }
    424         }
    425         List<XWPFParagraph> sourceParagraphs = source.getParagraphs();
    426         for (XWPFParagraph sourceParagraph : sourceParagraphs) {
    427             XWPFParagraph targetParagraph = target.addParagraph();
    428             copyParagraph(sourceParagraph, targetParagraph);
    429         }
    430     }
    431 
    432     /**
    433      * 复制表格行
    434      *
    435      * @param source 源
    436      * @param target 目标
    437      */
    438     private static void copyTableRow(XWPFTableRow source, XWPFTableRow target) {
    439         // 设置TableRow属性
    440         target.getCtRow().setTrPr(source.getCtRow().getTrPr());
    441 
    442         List<XWPFTableCell> sourceCells = source.getTableCells();
    443         List<XWPFTableCell> targetCells = target.getTableCells();
    444         //复制列及其属性和内容
    445         for (int pos = 0; pos < sourceCells.size(); pos++) {
    446             XWPFTableCell sourceCell = sourceCells.get(pos);
    447             XWPFTableCell targetCell = targetCells.get(pos);
    448             copyTableCell(sourceCell, targetCell);
    449         }
    450     }
    451 
    452 }
    View Code
  • 相关阅读:
    H.Playing games
    P4721 【模板】分治 FFT
    hdu5730 分治fft
    hdu6394Tree lct
    bzoj2763: [JLOI2011]飞行路线 最短路
    bzoj2154: Crash的数字表格 莫比乌斯反演
    bzoj3211: 花神游历各国 线段树
    溢流
    css控制继承
    “<textarea>”内的文字对齐
  • 原文地址:https://www.cnblogs.com/whirlwind/p/13625382.html
Copyright © 2020-2023  润新知