Record an HTML template to PDF

Keywords: Java xml Windows Apache

HTM template style and the actual conversion of pdf style will have a very large gap between the way to obtain templates is also very tortuous.
Here's a quick way to record it.

Step one:

The style here is exactly the same as that of html on the print page that calls windows on the front end; the left target printer selection: save as PDF
The pdf style saved here is exactly the same as the html style.

The second step:
Convert pdf saved in the previous step to word online address conversion pdf2word

The third step:
Convert the saved word from the previous step to html online address conversion word2html
The obtained template can be adjusted slightly.

I did this several times before I got the closest template.
If the style gap is large, you can adjust the transformation step by yourself and omit or several times.

The default.css file in the jar package may affect style

Pictures that support http links can be thrown in directly like regular strings

If the style is difficult and there are not many fields, it is recommended to use pdf template to transform the style without changing the disadvantage: the character length is totally limited by the domain and the image insertion is too arduous.

First introduce dependencies

        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.13</version>
        </dependency>
        <dependency>
            <groupId> com.itextpdf</groupId >
            <artifactId>itextpdf</artifactId >
            <version>5.5.9</version>
        </dependency>

        <dependency>
            <groupId> com.itextpdf</groupId >
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

The following is the code exported in batches that ignores business code

@RequestMapping(value="/exportPrintList")
    public void exportPdf(String keyword, String status, String createStartTime, String createEndTime, HttpServletResponse response)   {

        FileUtil.createDir(pdfFilePath,false);
        
        //Business code queries for data to be exported
        AppHealthtestEx ahe = new AppHealthtestEx();
        ahe.setType(HealthTestType.HealthTest.getType());
        ahe.setKeywords(keyword);
        ahe.setCreateStartTime(createStartTime);
        ahe.setCreateEndTime(createEndTime);
        if (StringUtils.isNotBlank(status)) {
            ahe.setStatus(Integer.parseInt(status));
        }
        ahe.setOrgOid(getSearchOrgOid());
        List<AppHealthtestEx> testNumbers = service.findPrintHealthtestEx(ahe);
        int corePoolSize = 5;
        if(testNumbers.size()<corePoolSize){
            corePoolSize = testNumbers.size();
        }

        if(corePoolSize>10){
            corePoolSize = 10;
        }
        // Batch Export Multiple Tasks
        ExecutorService executorService = new ThreadPoolExecutor(corePoolSize, testNumbers.size(), 0L,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(3));
        List<Future> result = Lists.newArrayList();

        AppPrintMode findPrintMode = new AppPrintMode();
        List<AppPrintMode> appPrintModes = appPrintModeService.find(findPrintMode);

        if(CollectionUtils.isNotEmpty(appPrintModes)){
            findPrintMode = appPrintModes.get(0);
        }

        int printMode = 1;
        if(findPrintMode.getPrintPlateType()!=null){
            printMode = findPrintMode.getPrintPlateType();
        }
        String template = "";
        if(printMode == 1){
            template = templatePath+"PrintAll.html";
        }else{
            template = templatePath +"PrintConcis.html";
        }
        for (AppHealthtestEx ex : testNumbers) {
            result.add(executorService.submit(new         
            PrintThread(pdfFilePath,ex.getTestNumber(),service,template,ex.getName())));
        }
        executorService.shutdown();
        try {
            executorService.awaitTermination(600,TimeUnit.SECONDS);

            FileUtil.compressToZip(pdfFilePath,filePath,"Export of Physical Examination Report.zip");
            service.downloadPdf(response,  "Export of Physical Examination Report.zip");
        }catch (Exception e){
            log.error("export pdf error : ",e);
        }
    }

Thread class:

import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.Callable;

public class PrintThread implements Callable{

    public Logger log = LoggerFactory.getLogger(this.getClass());
    private String fileFilePath;

    private String testNumber;

    private String templatePath;

    private AppHealthtestService appHealthtestService;

    private String fileName;

    public PrintThread(String fileFilePath, String testNumber, AppHealthtestService appHealthtestService,String templatePath,String fileName) {
        this.fileFilePath = fileFilePath;
        this.testNumber = testNumber;
        this.appHealthtestService = appHealthtestService;
        this.templatePath = templatePath;
        this.fileName = fileName;
    }

    @Override
    public Object call(){

        FileOutputStream fos = null;
        Document document = null;
        try {
            
            // Gets the values corresponding to all placeholders
            Map<String, Object> stringObjectMap = appHealthtestService.exportPreview(testNumber);
            String htmlContent = htmlSetValue(readString(templatePath),stringObjectMap);
            ByteArrayInputStream in = new ByteArrayInputStream(htmlContent.getBytes("UTF-8"));
            document = new Document(PageSize.A4);
            PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(fileFilePath+ fileName+testNumber + ".pdf"));
            document.open();

            document.addTitle("xxx Presentation");

            // Use our font provider and set it to unicode font style
            AsianFontProvider fontProvider = new AsianFontProvider();
            fontProvider.addFontSubstitute("lowagie", "garamond");
            // The production environment is windows. I am also windows locally. If you don't add this sentence in my locality, it's no problem. On the server, it's a mess pit.
            fontProvider.setUseUnicode(true);
            CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
            HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
            htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
            XMLWorkerHelper.getInstance().getDefaultCssResolver(true);

            XMLWorkerHelper.getInstance().parseXHtml(pdfWriter, document, in, null, Charset.forName("UTF-8"),
                    fontProvider);

           // XMLWorkerHelper.getInstance().parseXHtml(pdfWriter, document, in, Charset.forName("UTF-8"),new AsianFontProvider());
            document.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (document != null) {
                document.close();
            }
        }
        return "success";
    }
    
    // Read html template code
    private static String readString(String filePath) {
        File file = new File(filePath);
        String result = "";
        try {
            FileInputStream in = new FileInputStream(file);
            // size is the length of the string. Read it all at once.
            int size = in.available();
            byte[] buffer = new byte[size];
            in.read(buffer);
            in.close();
            result = new String(buffer,"UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }


   /**
     * Replace placeholders in templates
     * @param html Template code
     * @param map  Replacement template values
     * @return
     */
    private String htmlSetValue(String html,Map<String,Object> map){
        if(StringUtils.isBlank(html) || MapUtils.isEmpty(map)){
            return html;
        }
        for (String key : map.keySet()) {
            html = html.replaceAll("#"+key,MapUtils.getString(map,key,""));
        }
        return html;
    }

Font class:

public class AsianFontProvider extends XMLWorkerFontProvider {

    public AsianFontProvider() {
        super(null,null);
    }

    @Override
    public Font getFont(final String fontname, String encoding, float size, final int style) {
        String fntname = fontname;
        if (fntname == null) {
            fntname = "Song style";
        }
        if (size == 0) {
            size = 4;
        }
        return super.getFont(fntname, encoding, size, style);
    }
}

The HTML template is too big to stick a small section. Use # key to replace all placeholders with the values you want.
For example, the key value pair in map is: addres, Chaoyang District, Beijing, where the address is to be displayed in html, write address.

<td style="vertical-align:bottom; width:20pt">
                <p style="line-height:9pt; margin:0pt"><span style="font-family:'Microsoft YaHei'; font-size:8pt">land</span></p>
            </td>
        <td style="vertical-align:bottom; width:17pt" colspan="6">
                <p style="line-height:7pt; margin:0pt 0pt 0pt 10pt"><span style="font-family:'Microsoft YaHei';   font-size:7pt">Address:#address</span></p>
            </td>
        </tr>
        <tr style="height:9pt">
            <td style="vertical-align:bottom; width:20pt">
                <p style="line-height:9pt; margin:0pt"><span style="font-family:'Microsoft YaHei'; font-size:8pt">body</span></p>
            </td>
            <td style="vertical-align:bottom; width:87pt">
                <p style="line-height:9pt; margin:0pt 0pt 0pt 10pt"><span style="font-family:'Microsoft YaHei'; font-size:8pt">Gao:</span><span
                        style="font-family:'Microsoft YaHei'; font-size:8pt">#heightcm</span></p>
            </td>
            <td style="vertical-align:bottom; width:44pt">
                <p style="line-height:9pt; margin:0pt 0pt 0pt 24pt"><span style="font-family:'Microsoft YaHei'; font-size:8pt">body</span></p>
            </td>
            <td style="vertical-align:bottom; width:102pt">
                <p style="line-height:9pt; margin:0pt 0pt 0pt 9pt"><span style="font-family:'Microsoft YaHei'; font-size:8pt">Heavy:</span><span
                        style="font-family:'Microsoft YaHei'; font-size:8pt">#weightkg</span></p>
            </td> 

Posted by Paulus Magnus on Mon, 16 Sep 2019 00:11:43 -0700