一直用的是Template模板填充,这次需要填充文件,表格还是动态的哦,刚开始觉得有些难度,但是想想这不是一个挑战嘛,谁说编程很枯燥,我却觉得处处挑战,只要你敢尝试!
分享下实现的思路和逻辑还有坑坑:
1.先写个WordUtil:读取ftl文件将内容填充,这里的ftl文件是用doc转xml的呢~~
//生成word文件 byte[] fileByte = WordUtil.createWord(dataMap, project, ftl);
String project = "file";
/** * 生成word并且填充内容为字节 * @param dataMap * @param project * @param ftl * @return * @throws Exception */ public static byte[] createWord(Map<String, Object> dataMap, String project, String ftl) throws Exception { if (null == dataMap || dataMap.size() == 0){ return null; } //Configuration config = init(project); Configuration config = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS); config.setDefaultEncoding("UTF-8"); Resource resource = new ClassPathResource("template/" + project+"/"+ftl); byte[] bytes = null; try ( InputStream in = resource.getInputStream(); Reader reader = new InputStreamReader(in,"UTF-8"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); Writer out = new BufferedWriter(new OutputStreamWriter(baos,"UTF-8"));) { Template template = new Template("word",reader,config,"UTF-8"); template.process(dataMap, out); bytes = baos.toByteArray(); } catch (TemplateNotFoundException e) { throw new Exception("模板文件未找到:" + e.getMessage()); } catch (MalformedTemplateNameException e) { throw new Exception("模板类型不正确:" + e.getMessage()); } return bytes; }
2. word(xml格式)转成pdf用的是aspose-word技术
//word转换pdf byte[] pdfByte = WordPdfUtil.docFile2pdf(new ByteArrayInputStream(fileByte));
public static byte[] docFile2pdf(ByteArrayInputStream is) { if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生 return null; } byte[] buffer = null; try { //字体设置 FontSettings.setFontsFolder("/home/logs/supervisor/fonts",true); Document doc = new Document(is); // Address是将要被转化的word文档 ByteArrayOutputStream bos = new ByteArrayOutputStream(); doc.save(bos, SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,os.close(); bos.close(); buffer = bos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } return buffer; }
这个坑花了我很长时间的就是如果是上传linux格式乱码,因为字体。FontSettings设置字体 ,编码统一UTF-8
解决了,,生成的文件格式就是pdf的byte字节流了
另外如果是要xml转成doc格式(不是docx格式的话就需要保存Doc)
public static byte[] docFile2doc(ByteArrayInputStream is) { if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生 return null; } byte[] buffer = null; try { FontSettings.setFontsFolder("/home/hanchen/logs/supervisor/fonts",true); Document doc = new Document(is); // Address是将要被转化的word文档 ByteArrayOutputStream bos = new ByteArrayOutputStream(); doc.save(bos, SaveFormat.DOC);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,os.close(); bos.close(); buffer = bos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } return buffer; }
引用的依赖:
<dependency> <groupId>com.aspose</groupId> <artifactId>aspose-words</artifactId> <version>15.8.0</version> </dependency>
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <scope>compile</scope> </dependency>
二. Word转Pdf文件
这个是xml转化的pdf,对了,,如果是要word(doc/docx)转化的话,提供另外一种思路吧:
//word转pdf
response.setContentType("application/pdf"); //respose方式是输出 outputStream = response.getOutputStream(); if (extName.startsWith(SysConstants.DOCUMENT_SUFFIX_DOC)) { if (StringUtils.equalsIgnoreCase(SysConstants.DOCUMENT_SUFFIX_DOCX, extName)) { docxToPdf(bytes, outputStream); } else if (StringUtils.equalsIgnoreCase(SysConstants.DOCUMENT_SUFFIX_DOC, extName)) { wordConverter2003ToPdf(bytes,outputStream); } }
/** * docx 转pdf * * @param bytes * @param outputStream * @throws IOException */ private void docxToPdf(byte[] bytes, ServletOutputStream outputStream) throws IOException { PdfOptions options = PdfOptions.create(); //支持中文字体 options.fontProvider(new ITextFontRegistry() { @Override public Font getFont(String familyName, String encoding, float size, int style, Color color) { try { BaseFont bfChinese = BaseFont.createFont("fonts/simfang.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); Font fontChinese = new Font(bfChinese, size, style, color); if (familyName != null) { fontChinese.setFamily(familyName); } return fontChinese; } catch (Throwable e) { e.printStackTrace(); return ITextFontRegistry.getRegistry().getFont(familyName, encoding, size, style, color); } } }); XWPFDocument document = new XWPFDocument(new ByteArrayInputStream(bytes)); PdfConverter.getInstance().convert(document, outputStream, options); } /** * doc转pdf * @param bytes * @param outputStream * @throws Exception */ public static void wordConverter2003ToPdf(byte[] bytes, ServletOutputStream outputStream) throws Exception { POIFSFileSystem fs = null; Document document = new Document(); try { fs = new POIFSFileSystem(new ByteArrayInputStream(bytes)); HWPFDocument doc = new HWPFDocument(fs); WordExtractor we = new WordExtractor(doc); String text2003 =we.getText(); PdfWriter writer = PdfWriter.getInstance(document, outputStream); Range range = doc.getRange(); document.open(); writer.setPageEmpty(true); document.newPage(); String[] paragraphs = we.getParagraphText(); BaseFont bfChinese = BaseFont.createFont("fonts/simfang.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); Font font = new Font(bfChinese, 14, Font.NORMAL); //font.setFamily("Droid Sans"); for (int i = 0; i < paragraphs.length; i++) { org.apache.poi.hwpf.usermodel.Paragraph pr = range.getParagraph(i); paragraphs[i] = paragraphs[i].replaceAll("\\cM?\r?\n", ""); document.add(new Paragraph(paragraphs[i],font)); } }catch (Exception e) { e.printStackTrace(); }finally { document.close(); } }
另外我同事跟我说他遇到困难的时候是兴奋开心的,有的人是害怕的,所以技术越来越好,还通过这个功能学会用流怎么输入输出,再看下用到的技术实现,发现pdf的填充还有一种是html来填充的,后面会分享,点个赞吧!❥(^_-)