Generating Docx and Pdf files based on Freemarker template

The product raises the requirement of generating a word document and a pdf document respectively, which need to contain data, which need to have corresponding styles such as font size, tables, paragraphs and so on. The initial idea was to use Apache POI, but after looking at that large piece of code for filling in value operations, it was found that it was too lengthy and decided to adopt the Freemarker template.
Baidu looks like a circleSpring Boot + FreeMarker Making Word Template and Exporting Word Form It's like that. After a wave of attempts, it turns out that only documents in doc format can be generated! Only documents in doc format can be generated! Only documents in doc format can be generated! What I want is docx format?
I had to go through a long search attempt to fail and then search again to fail... Well, finally I found a way to generate docx:
1. Modify the docx suffix to zip and take out the document.xml document and the document.xml.rels document under the _rels folder.
document.xml is a file that needs to be used to fill text content, such as you can modify it like this.

When generating a new docx, replace the ${} content with the parameters we passed in. As for how to organize the template, and the freemarker loop, judge these grammars by Baidu itself, easy! ____________
document.xml.rels is the file that you need to replace the pictures in your docx, such as I will use the original

<Relationship Id="rId8" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.jpeg"/>

Replaced

<Relationship Id="rId8" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/${img.imgTargetName}"/>

I replaced image1.jpeg with the image corresponding to the variable ${img.imgTargetName}. Of course, the media folder in the zip package also needs to write in the new image file. It should be noted that the suffix name of the new file is the same as the suffix name of the original file, otherwise the generated docx may not open.
2. Read the zip file compression stream, replace the original document.xml, document.xml.rel file with the filled document.xml, document.xml.rels file, and write the picture to the word/media folder under the zip file.
Output docx document.
Upper code

    public static String exportImgWordDocx(Map map,String wordXmlName,String wordImgXmlResName)
            throws Exception {
        Template freemarkerTemplate = configuration.getTemplate(wordXmlName);
        Template imgFreemarkerTemplate = configuration.getTemplate(wordImgXmlResName);
        InputStream fin = null;
        ServletOutputStream out = null;
        Writer writerOut = null;
        Writer writerOutImg = null;
        File outdocxXmlFile =null;
        File outdocxImgXmlFile = null;
        File docxFile = null;
        String docxPath = null;
        try {
            //Specify the path to the output word docx data file
            String outdocxXmlFilePath = exportResourcePath+UUID.randomUUID().toString()+".xml";
            outdocxXmlFile = new File(outdocxXmlFilePath);
            FileOutputStream fos = new FileOutputStream(outdocxXmlFile);
            writerOut = new BufferedWriter(new OutputStreamWriter(fos),10240);
            //Write map data into xml template to get docx data file
            freemarkerTemplate.process(map,writerOut);


            //Specify the path to output the word docx image data file
            String outdocxImgXmlFilePath = exportResourcePath+UUID.randomUUID().toString()+".xml.rels";
            outdocxImgXmlFile = new File(outdocxImgXmlFilePath);
            FileOutputStream fosImg = new FileOutputStream(outdocxImgXmlFile);
            writerOutImg = new BufferedWriter(new OutputStreamWriter(fosImg),10240);
            //Write map data into image xml template to get docx image data file
            imgFreemarkerTemplate.process(map,writerOutImg);


            //Replace the docx Data xml file and the image data xml file with the corresponding docx instance zip compression package
            ClassPathResource resource = new ClassPathResource("templates/SummaryTemplate.zip");
            InputStream zipFileInputStream = resource.getInputStream();

            docxPath = exportResourcePath +UUID.randomUUID().toString()+".docx";
            docxFile = new File(docxPath);

            ZipInputStream zipInputStream = ZipUtils.wrapZipInputStream(zipFileInputStream);
            ZipOutputStream zipOutputStream = ZipUtils.wrapZipOutputStream(new FileOutputStream(docxFile));
            String itemNameOne = "word/document.xml";
            String itemNameTwo = "word/_rels/document.xml.rels";
            List<Map<String,String>> imgList = (List<Map<String,String>>)map.get("imgList");
            ZipUtils.replaceTwoItem(zipInputStream, zipOutputStream, itemNameOne, new FileInputStream(outdocxXmlFile),itemNameTwo,new FileInputStream(outdocxImgXmlFile),imgList);


        } catch (TemplateException e) {
            StackTraceElement[] stackTraceElements = e.getStackTrace();
            logger.error(e.toString() + "---" + stackTraceElements[0].toString());
            throw new SystemRunException(e.toString() + "---" + stackTraceElements[0].toString());
        }finally {
            if (out != null) {
                out.close();
            }
            if (fin != null) {
                fin.close();
            }
            if(writerOut != null){
                writerOut.close();
            }
            if(writerOutImg != null){
                writerOutImg.close();
            }
            if(outdocxXmlFile!=null){
                outdocxXmlFile.delete();//Delete docx temporary data file
            }
            if(outdocxImgXmlFile!=null){
                //outdocxImgXmlFile.delete(); //Delete docx temporary picture data file
            }
            if(docxFile!=null){
                //docxFile.delete();//Delete docx temporary files
            }
        }
        return docxPath;
    }

If you need to generate pdf format files, you also need to convert them into pdf format files as docx format files. As for the conversion process, the simplest and reliable solution I found is to use asponse-words, but this is a fee-paying software. Many jar downloads in csdn are free from cracking, and the generated pdf files will be watermarked.
Upper Code:

public static void asposeWord2Pdf(String docxPath,String pdfPath){
        logger.info("docxPath" + docxPath + "pdfPath" + pdfPath);

        if (!getLicense()) {
            return;
        }
        FileOutputStream os =null;
        try {
            File file = new File(pdfPath); // Create a new blank pdf document
            os = new FileOutputStream(file);
            Document doc = new Document(docxPath); // Address is the word document to be transformed
            doc.save(os, SaveFormat.PDF);
        } catch (Exception e) {
            StackTraceElement[] stackTraceElements = e.getStackTrace();
            logger.error(e.toString() + "---" + stackTraceElements[0].toString());
            throw new SystemRunException(e.toString() + "---" + stackTraceElements[0].toString());
        }finally{
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

Later, you may encounter the problem of SpringBoot referring to external jar s. The generated Pdf files are all small boxes. All kinds of problems of slow file generation need to be solved patiently. Don't ask me how I know... Cry!

The following are the big boys:

java Generates word Documents in Dox Format Using Freemarker Template

java uses Freemarker template to generate format-friendly doc or docx documents

freemarker creates template based on docx format to export pdf files with pictures

Tags: Java xml FreeMarker Apache

Posted on Thu, 10 Oct 2019 20:22:54 -0700 by hillbilly928