Itext处理阿拉伯文本时,对html样式dir=‘rtl‘不生效的2种解决方案

第一种方案简单快捷方便: 修改Itextrenderer.java

第二种方案:把阿拉伯文本写到图片里,再把图片写到pdf

Itextrenderer.java(itext5.x)

package com.demo.controller;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Shape;
import java.io.*;
import java.util.List;
import java.util.regex.Pattern;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.interfaces.PdfRunDirection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xhtmlrenderer.context.StyleReference;
import org.xhtmlrenderer.css.style.CalculatedStyle;
import org.xhtmlrenderer.extend.NamespaceHandler;
import org.xhtmlrenderer.extend.UserInterface;
import org.xhtmlrenderer.layout.BoxBuilder;
import org.xhtmlrenderer.layout.Layer;
import org.xhtmlrenderer.layout.LayoutContext;
import org.xhtmlrenderer.layout.SharedContext;
import org.xhtmlrenderer.pdf.*;
import org.xhtmlrenderer.render.BlockBox;
import org.xhtmlrenderer.render.PageBox;
import org.xhtmlrenderer.render.RenderingContext;
import org.xhtmlrenderer.render.ViewportBox;
import org.xhtmlrenderer.resource.XMLResource;
import org.xhtmlrenderer.simple.extend.XhtmlNamespaceHandler;
import org.xhtmlrenderer.util.Configuration;
import org.xml.sax.InputSource;

import com.itextpdf.text.pdf.PdfWriter;

/**重写ITextRenderer*/
public class ITextRenderer {
    // These two defaults combine to produce an effective resolution of 96 px to
    // the inch
    private static final float DEFAULT_DOTS_PER_POINT = 20f * 4f / 3f;
    private static final int DEFAULT_DOTS_PER_PIXEL = 20;

    private final SharedContext _sharedContext;
    private final ITextOutputDevice _outputDevice;

    private Document _doc;
    private BlockBox _root;

    private final float _dotsPerPoint;

    private com.itextpdf.text.Document _pdfDoc;
    private PdfWriter _writer;

    private PDFEncryption _pdfEncryption;

    // note: not hard-coding a default version in the _pdfVersion field as this
    // may change between iText releases
    // check for null before calling writer.setPdfVersion()
    // use one of the values in PDFWriter.VERSION...
    private Character _pdfVersion;

    private final char[] validPdfVersions = new char[] { PdfWriter.VERSION_1_2, PdfWriter.VERSION_1_3, PdfWriter.VERSION_1_4,
            PdfWriter.VERSION_1_5, PdfWriter.VERSION_1_6, PdfWriter.VERSION_1_7 };

    private PDFCreationListener _listener;

    public ITextRenderer() {
        this(DEFAULT_DOTS_PER_POINT, DEFAULT_DOTS_PER_PIXEL);
    }

    public ITextRenderer(float dotsPerPoint, int dotsPerPixel) {
        _dotsPerPoint = dotsPerPoint;

        _outputDevice = new ITextOutputDevice(_dotsPerPoint);

        ITextUserAgent userAgent = new ITextUserAgent(_outputDevice);
        _sharedContext = new SharedContext();
        _sharedContext.setUserAgentCallback(userAgent);
        _sharedContext.setCss(new StyleReference(userAgent));
        userAgent.setSharedContext(_sharedContext);
        _outputDevice.setSharedContext(_sharedContext);

        ITextFontResolver fontResolver = new ITextFontResolver(_sharedContext);
        _sharedContext.setFontResolver(fontResolver);

        ITextReplacedElementFactory replacedElementFactory = new ITextReplacedElementFactory(_outputDevice);
        _sharedContext.setReplacedElementFactory(replacedElementFactory);

        _sharedContext.setTextRenderer(new ITextTextRenderer());
        _sharedContext.setDPI(72 * _dotsPerPoint);
        _sharedContext.setDotsPerPixel(dotsPerPixel);
        _sharedContext.setPrint(true);
        _sharedContext.setInteractive(false);
    }

    public Document getDocument() {
        return _doc;
    }

    public ITextFontResolver getFontResolver() {
        return (ITextFontResolver) _sharedContext.getFontResolver();
    }

    private Document loadDocument(final String uri) {
        return _sharedContext.getUac().getXMLResource(uri).getDocument();
    }

    public void setDocument(String uri) {
        setDocument(loadDocument(uri), uri);
    }

    public void setDocument(Document doc, String url) {
        setDocument(doc, url, new XhtmlNamespaceHandler());
    }

    public void setDocument(File file) throws IOException {

        File parent = file.getAbsoluteFile().getParentFile();
        setDocument(loadDocument(file.toURI().toURL().toExternalForm()), (parent == null ? "" : parent.toURI().toURL().toExternalForm()));
    }

    public void setDocumentFromString(String content) {
        setDocumentFromString(content, null);
    }

    public void setDocumentFromString(String content, String baseUrl) {
        InputSource is = new InputSource(new BufferedReader(new StringReader(content)));
        Document dom = XMLResource.load(is).getDocument();

        setDocument(dom, baseUrl);
    }

    public void setDocument(Document doc, String url, NamespaceHandler nsh) {
        _doc = doc;

        getFontResolver().flushFontFaceFonts();

        _sharedContext.reset();
        if (Configuration.isTrue("xr.cache.stylesheets", true)) {
            _sharedContext.getCss().flushStyleSheets();
        } else {
            _sharedContext.getCss().flushAllStyleSheets();
        }
        _sharedContext.setBaseURL(url);
        _sharedContext.setNamespaceHandler(nsh);
        _sharedContext.getCss().setDocumentContext(_sharedContext, _sharedContext.getNamespaceHandler(), doc, new NullUserInterface());
        getFontResolver().importFontFaces(_sharedContext.getCss().getFontFaceRules());
    }

    public PDFEncryption getPDFEncryption() {
        return _pdfEncryption;
    }

    public void setPDFEncryption(PDFEncryption pdfEncryption) {
        _pdfEncryption = pdfEncryption;
    }

    public void setPDFVersion(char _v) {
        for (int i = 0; i < validPdfVersions.length; i++) {
            if (_v == validPdfVersions[i]) {
                _pdfVersion = new Character(_v);
                return;
            }
        }
        throw new IllegalArgumentException("Invalid PDF version character; use "
                + "valid constants from PdfWriter (e.g. PdfWriter.VERSION_1_2)");
    }

    public char getPDFVersion() {
        return _pdfVersion == null ? '0' : _pdfVersion.charValue();
    }

    public void layout() {
        LayoutContext c = newLayoutContext();
        BlockBox root = BoxBuilder.createRootBox(c, _doc);
        root.setContainingBlock(new ViewportBox(getInitialExtents(c)));
        root.layout(c);
        Dimension dim = root.getLayer().getPaintingDimension(c);
        root.getLayer().trimEmptyPages(c, dim.height);
        root.getLayer().layoutPages(c);
        _root = root;
    }

    private Rectangle getInitialExtents(LayoutContext c) {
        PageBox first = Layer.createPageBox(c, "first");

        return new Rectangle(0, 0, first.getContentWidth(c), first.getContentHeight(c));
    }

    private RenderingContext newRenderingContext() {
        RenderingContext result = _sharedContext.newRenderingContextInstance();
        result.setFontContext(new ITextFontContext());

        result.setOutputDevice(_outputDevice);

        _sharedContext.getTextRenderer().setup(result.getFontContext());

        result.setRootLayer(_root.getLayer());

        return result;
    }

    private LayoutContext newLayoutContext() {
        LayoutContext result = _sharedContext.newLayoutContextInstance();
        result.setFontContext(new ITextFontContext());

        _sharedContext.getTextRenderer().setup(result.getFontContext());

        return result;
    }

    public void createPDF(OutputStream os) throws DocumentException, IOException {
        createPDF(os, true, 0);
    }

    public void writeNextDocument() throws DocumentException, IOException {
        writeNextDocument(0);
    }

    public void writeNextDocument(int initialPageNo) throws DocumentException, IOException {
        List pages = _root.getLayer().getPages();

        RenderingContext c = newRenderingContext();
        c.setInitialPageNo(initialPageNo);
        PageBox firstPage = (PageBox) pages.get(0);
        com.itextpdf.text.Rectangle firstPageSize = new com.itextpdf.text.Rectangle(0, 0, firstPage.getWidth(c) / _dotsPerPoint,
                firstPage.getHeight(c) / _dotsPerPoint);

        _outputDevice.setStartPageNo(_writer.getPageNumber());

        _pdfDoc.setPageSize(firstPageSize);
        _pdfDoc.newPage();

        writePDF(pages, c, firstPageSize, _pdfDoc, _writer);
    }

    public void finishPDF() {
        if (_pdfDoc != null) {
            _pdfDoc.close();
        }
    }

    public void createPDF(OutputStream os, boolean finish) throws DocumentException, IOException {
        createPDF(os, finish, 0);
    }

    /**
     * <B>NOTE:</B> Caller is responsible for cleaning up the OutputStream if
     * something goes wrong.
     *
     * @throws IOException
     */
    public void createPDF(OutputStream os, boolean finish, int initialPageNo) throws DocumentException, IOException {
        List pages = _root.getLayer().getPages();

        RenderingContext c = newRenderingContext();
        c.setInitialPageNo(initialPageNo);
        PageBox firstPage = (PageBox) pages.get(0);
        com.itextpdf.text.Rectangle firstPageSize = new com.itextpdf.text.Rectangle(0, 0, firstPage.getWidth(c) / _dotsPerPoint,
                firstPage.getHeight(c) / _dotsPerPoint);

        com.itextpdf.text.Document doc = new com.itextpdf.text.Document(firstPageSize, 0, 0, 0, 0);
        PdfWriter writer = PdfWriter.getInstance(doc, os);
        if (_pdfVersion != null) {
            writer.setPdfVersion(_pdfVersion.charValue());
        }
        if (_pdfEncryption != null) {
            writer.setEncryption(_pdfEncryption.getUserPassword(), _pdfEncryption.getOwnerPassword(),
                    _pdfEncryption.getAllowedPrivileges(), _pdfEncryption.getEncryptionType());
        }
        _pdfDoc = doc;
        _writer = writer;

        doc.open();

        BaseFont BFont_SimHei = BaseFont.createFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        Font Font_SimHei = new Font(BFont_SimHei);
        ColumnText column1 = new ColumnText(writer.getDirectContent());
        Chunk Chu_Name1 = new Chunk(ARABIC, Font_SimHei);//建议这样写,位置页放在doc.open后面,如果多页的话,这样就出现在第一页
        column1.addText(Chu_Name1);
        column1.addText(Chunk.NEWLINE);
        column1.setSimpleColumn(18, 300, 480, 570);//位置需要自己调试哟
        column1.setRunDirection(PdfWriter.RUN_DIRECTION_LTR);
        int status1 = column1.go();
        System.out.println(column1.getLinesWritten());
        System.out.println(ColumnText.hasMoreText(status1));

        writePDF(pages, c, firstPageSize, doc, writer);

        if (finish) {

//            Font font = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//            Phrase p =new Phrase();
//            p.add(new Chunk(ARABIC, font));//不建议这样写,发现PDF里出现重复2次,没时间研究为什么会这样
//            doc.add(p);
//
//            ColumnText c1= new ColumnText(writer.getDirectContent());
//            c1.setSimpleColumn(76,450,559,780);
//            c1.setRunDirection(PdfWriter.RUN_DIRECTION_LTR);
//            c1.addElement(p);
//            c1.go();
//

//            BaseFont BFont_SimKai = BaseFont.createFont(YH, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//            Font Font_SimKai = new Font(BFont_SimKai);
//
//            ColumnText column = new ColumnText(writer.getDirectContent());
//            Chunk Chu_Name = new Chunk(ARABIC+"AAAAA", Font_SimHei);//如果放在doc.close之前,会展示在最后一页
            Chunk Chu_NameContent = new Chunk("张三", Font_SimKai);
//            column.addText(Chu_Name);
            column.addText(Chu_NameContent);
//            column.addText(Chunk.NEWLINE);
//
            Chunk Chu_Age = new Chunk("年龄:", Font_SimKai);
            Chunk Chu_AgeContent = new Chunk("35岁", Font_SimKai);
            column.addText(Chu_Age);
            column.addText(Chu_AgeContent);
//            column.setSimpleColumn(18, 300, 480, 570);
//            column.setRunDirection(PdfWriter.RUN_DIRECTION_LTR);
//            int status = column.go();
//            System.out.println(column.getLinesWritten());
//            System.out.println(ColumnText.hasMoreText(status));
            doc.close();
        }
    }
    public static final String FONT ="D:\\gitee\\font\\ARIALUNI.TTF";
    public static final String YH ="D:\\gitee\\font\\msyh.ttf";
    public static final String ARABIC = "Aربط صفحة على شبكة الإنترنت 链接网页";

    private void writePDF(List pages, RenderingContext c, com.itextpdf.text.Rectangle firstPageSize, com.itextpdf.text.Document doc,
                          PdfWriter writer) throws DocumentException, IOException {
        _outputDevice.setRoot(_root);

        _outputDevice.start(_doc);
        _outputDevice.setWriter(writer);
        _outputDevice.initializePage(writer.getDirectContent(), firstPageSize.getHeight());

        _root.getLayer().assignPagePaintingPositions(c, Layer.PAGED_MODE_PRINT);

        int pageCount = _root.getLayer().getPages().size();
        c.setPageCount(pageCount);
//        firePreWrite(pageCount); // opportunity to adjust meta data
        setDidValues(doc); // set PDF header fields from meta data
        for (int i = 0; i < pageCount; i++) {
            PageBox currentPage = (PageBox) pages.get(i);
            c.setPage(i, currentPage);
            paintPage(c, writer, currentPage);
            _outputDevice.finishPage();
            if (i != pageCount - 1) {
                PageBox nextPage = (PageBox) pages.get(i + 1);
                com.itextpdf.text.Rectangle nextPageSize = new com.itextpdf.text.Rectangle(0, 0, nextPage.getWidth(c) / _dotsPerPoint,
                        nextPage.getHeight(c) / _dotsPerPoint);
                doc.setPageSize(nextPageSize);
                doc.newPage();
                _outputDevice.initializePage(writer.getDirectContent(), nextPageSize.getHeight());
            }
        }

        _outputDevice.finish(c, _root);
    }

    // Sets the document information dictionary values from html metadata
    private void setDidValues(com.itextpdf.text.Document doc) {
        String v = _outputDevice.getMetadataByName("title");
        if (v != null) {
            doc.addTitle(v);
        }
        v = _outputDevice.getMetadataByName("author");
        if (v != null) {
            doc.addAuthor(v);
        }
        v = _outputDevice.getMetadataByName("subject");
        if (v != null) {
            doc.addSubject(v);
        }
        v = _outputDevice.getMetadataByName("keywords");
        if (v != null) {
            doc.addKeywords(v);
        }
    }

    private void paintPage(RenderingContext c, PdfWriter writer, PageBox page) throws IOException {
        provideMetadataToPage(writer, page);

        page.paintBackground(c, 0, Layer.PAGED_MODE_PRINT);
        page.paintMarginAreas(c, 0, Layer.PAGED_MODE_PRINT);
        page.paintBorder(c, 0, Layer.PAGED_MODE_PRINT);

        Shape working = _outputDevice.getClip();

        Rectangle content = page.getPrintClippingBounds(c);
        _outputDevice.clip(content);

        int top = -page.getPaintingTop() + page.getMarginBorderPadding(c, CalculatedStyle.TOP);

        int left = page.getMarginBorderPadding(c, CalculatedStyle.LEFT);

        _outputDevice.translate(left, top);
        _root.getLayer().paint(c);
        _outputDevice.translate(-left, -top);

        _outputDevice.setClip(working);
    }

    private void provideMetadataToPage(PdfWriter writer, PageBox page) throws IOException {
        byte[] metadata = null;
        if (page.getMetadata() != null) {
            try {
                String metadataBody = stringfyMetadata(page.getMetadata());
                if (metadataBody != null) {
                    metadata = createXPacket(stringfyMetadata(page.getMetadata())).getBytes("UTF-8");
                }
            } catch (UnsupportedEncodingException e) {
                // Can't happen
                throw new RuntimeException(e);
            }
        }

        if (metadata != null) {
            writer.setPageXmpMetadata(metadata);
        }
    }

    private String stringfyMetadata(Element element) {
        Element target = getFirstChildElement(element);
        if (target == null) {
            return null;
        }

        try {
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter output = new StringWriter();
            transformer.transform(new DOMSource(target), new StreamResult(output));

            return output.toString();
        } catch (TransformerConfigurationException e) {
            // Things must be in pretty bad shape to get here so
            // rethrow as runtime exception
            throw new RuntimeException(e);
        } catch (TransformerException e) {
            throw new RuntimeException(e);
        }
    }

    private static Element getFirstChildElement(Element element) {
        Node n = element.getFirstChild();
        while (n != null) {
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                return (Element) n;
            }
            n = n.getNextSibling();
        }
        return null;
    }

    private String createXPacket(String metadata) {
        StringBuffer result = new StringBuffer(metadata.length() + 50);
        result.append("<?xpacket begin='\uFEFF' id='W5M0MpCehiHzreSzNTczkc9d'?>\n");
        result.append(metadata);
        result.append("\n<?xpacket end='r'?>");

        return result.toString();
    }

    public ITextOutputDevice getOutputDevice() {
        return _outputDevice;
    }

    public SharedContext getSharedContext() {
        return _sharedContext;
    }

    public void exportText(Writer writer) throws IOException {
        RenderingContext c = newRenderingContext();
        c.setPageCount(_root.getLayer().getPages().size());
        _root.exportText(c, writer);
    }

    public BlockBox getRootBox() {
        return _root;
    }

    public float getDotsPerPoint() {
        return _dotsPerPoint;
    }

    public List findPagePositionsByID(Pattern pattern) {
        return _outputDevice.findPagePositionsByID(newLayoutContext(), pattern);
    }

    private static final class NullUserInterface implements UserInterface {
        public boolean isHover(Element e) {
            return false;
        }

        public boolean isActive(Element e) {
            return false;
        }

        public boolean isFocus(Element e) {
            return false;
        }
    }

    public PDFCreationListener getListener() {
        return _listener;
    }

    public void setListener(PDFCreationListener listener) {
        _listener = listener;
    }

    public PdfWriter getWriter() {
        return _writer;
    }
}

ImageImpl.java
package com.demo.controller;

import org.apache.tomcat.util.codec.binary.Base64;
import org.krysalis.barcode4j.tools.UnitConv;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**建议用自定义字体,Graphics2D 里的字体个人感觉不太好看*/
public class ImageImpl {
    //初始的宽度
    private static final int START_WIDTH = 0;
    //初始的高度
    private static final int START_HEIGHT = 0;
    //图片的宽度
    private static final int IMG_WIDTH = (int) UnitConv.mm2pt(100);
    //图片的宽度
    private static final int IMG_HEIGHT = (int) UnitConv.mm2pt(140);
    private static final String ARIALUNI = "D:\\gitee\\font\\ARIALUNI.TTF";

    private Font definedFont = null;

    public Font getDefinedFont(int ft,float fs) {
        InputStream is = null;
        BufferedInputStream bis = null;
        try {
            is = new FileInputStream(new File(ARIALUNI));
            bis = new BufferedInputStream(is);
            definedFont = Font.createFont(Font.TRUETYPE_FONT, is);
            //设置字体大小,float型
            definedFont = definedFont.deriveFont(fs);
        } catch (FontFormatException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != bis) {
                    bis.close();
                }
                if (null != is) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return definedFont;
    }

    /**
     * 文字超出限定长度自动换行
     *
     * @param g           画布
     * @param font        字体样式
     * @param text        文字
     * @param widthLength 最大长度  (多少长度后需要换行)
     * @param x           文字位置坐标  x
     * @param y           文字位置坐标 Y
     * @param yn          每次换行偏移多少pt
     */
    private void drawString(Graphics2D g, Font font, String text, int widthLength, int x, int y, int yn) {

        FontMetrics fg = g.getFontMetrics(font);
        java.util.List<String> ls = new ArrayList<>(2);
        getListText(fg, text, widthLength, ls);
        int size = ls.size();
        for (int i = 0; i < ls.size(); i++) {
            if (i == 0) {
                g.drawString(ls.get(i), (int) UnitConv.mm2pt(x), (int) UnitConv.mm2pt(y));
            } else {
                g.drawString(ls.get(i), (int) UnitConv.mm2pt(x), (int) UnitConv.mm2pt(y + yn));
            }
        }
    }

    private void buildTheSketchpad(Graphics2D g) {

        Font addressFont = new Font("Arial Unicode MS", Font.PLAIN, 12);
        g.setFont(addressFont);
        //设置背景色为白色
//        g.setColor(Color.white);
        g.setBackground(Color.white);
        //设置颜色区域大小
        g.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
        /*
         * 绘制表格 填充内容
         * */
        //表格线条的颜色
        g.setColor(Color.BLACK);

        //消除文本出现锯齿现象
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
        //表格的四个边框

        // 上边框
//        g.drawLine(START_WIDTH, START_HEIGHT, START_WIDTH + (int) UnitConv.mm2pt(100), START_HEIGHT);
        //左边框
//        g.drawLine(START_WIDTH, START_HEIGHT, START_WIDTH, START_HEIGHT + (int) UnitConv.mm2pt(120));
        //右边框
//        g.drawLine(START_WIDTH, START_HEIGHT + (int) UnitConv.mm2pt(120), START_WIDTH + (int) UnitConv.mm2pt(99), START_HEIGHT + (int) UnitConv.mm2pt(119));
        //下边框
//        g.drawLine(START_WIDTH + (int) UnitConv.mm2pt(100), START_HEIGHT, START_WIDTH + (int) UnitConv.mm2pt(99), START_HEIGHT + (int) UnitConv.mm2pt(119));

    }
    /**
     * @param g           画布
     * @param province    收件人 省    河北
     * @param city        收件人 市    石家庄
     * @param area        收件人 区    无名
     * @param address     收件人 地址   天天阿里中文路为大帝滴滴aaaaaa为大帝滴滴aass大帝
     * @param name        收件人 姓名   李先生
     * @param mobilePhone 收件人 手机    19210001200
     * @param phone       收件人 电话    1230-15151-8481
     */
    private void partB(Graphics2D g, String province, String city, String area, String address, String name, String mobilePhone, String phone) {
//        g.drawLine(START_WIDTH + (int) UnitConv.mm2pt(10), START_HEIGHT + (int) UnitConv.mm2pt(38), START_WIDTH + (int) UnitConv.mm2pt(10), START_HEIGHT + (int) UnitConv.mm2pt(55));

//        Font addressFont = new Font("Arial Unicode MS", Font.PLAIN, 12);
        Font addressFont = getDefinedFont(1,34f);
        g.setFont(addressFont);
//        g.drawString("收", (int) UnitConv.mm2pt(3), (int) UnitConv.mm2pt(43));
//        g.drawString("件", (int) UnitConv.mm2pt(3), (int) UnitConv.mm2pt(49));
//        g.drawString("人", (int) UnitConv.mm2pt(3), (int) UnitConv.mm2pt(53));
//        String s = province + " " + city + " " + area + " " + address;
        String s = address;
        String add = "河北 石家庄 天天阿里中文路为大帝滴滴aaaaaa为大帝滴滴";
        drawString(g, addressFont, s, 500, 12, 43, 8);
        String name2 = "李先生 19210001200 1230-15151-8481";
        String d = name + " " + mobilePhone + " " + phone;
//        g.drawString(d, (int) UnitConv.mm2pt(12), (int) UnitConv.mm2pt(52));

        // 收件人下划线
//        g.drawLine(START_HEIGHT, START_WIDTH + (int) UnitConv.mm2pt(54), START_WIDTH + (int) UnitConv.mm2pt(100), START_HEIGHT + (int) UnitConv.mm2pt(54));
    }

    public String createApiCture() throws IOException {
        ZjsPrintOrderParam z=new ZjsPrintOrderParam();
        z.setSAddress("用户:ربط صفحة على شبكة الإنترنت您好");
        z.setSProvince("provice");
        z.setSCity("city");
        z.setSArea("area");
        z.setSName("name");
        z.setSMobilePhone("mphone");
        z.setSPhone("phone");

        BufferedImage image = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        // 创建画板
        buildTheSketchpad(g);
        // 画B部分
        partB(g, z.getSProvince(), z.getSCity(), z.getSArea(), z.getSAddress(), z.getSName(), z.getSMobilePhone(), z.getSPhone());
        g.dispose();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(image, "PNG", os);
//        return os.toByteArray();
        //ImageIO.write(image, "PNG", new File(STORE_PATH));
        return Base64.encodeBase64String(os.toByteArray());
    }

    /**
     * 递归 切割字符串
     * @param fg
     * @param text
     * @param widthLength
     * @param ls
     */
    private void getListText(FontMetrics fg, String text, int widthLength, List<String> ls) {
        String ba = text;
        boolean b = true;
        int i = 1;
        while (b) {
            if (fg.stringWidth(text) > widthLength) {
                text = text.substring(0, text.length() - 1);
                i++;
            } else {
                b = false;
            }
        }
        if (i != 1) {
            ls.add(ba.substring(0, ba.length() - i));
            getListText(fg, ba.substring(ba.length() - i), widthLength, ls);
        } else {
            ls.add(text);
        }
    }


}

main()

public static void main(String[] args) throws IOException, DocumentException, DocumentException {
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("name", "路奇.D.艾尼路");
        File file = new File(LOGO_PATH);
        data.put("fileType", "image/jpeg");
        data.put("file64Str",fileToBase64Str(file));
        data.put("order", "12orderAA");
        data.put("orderId", "12order");
        data.put("pod", "CN1233aaa");
        data.put("podCode", "CN1233");
        ImageImpl image = new ImageImpl();

       // data.put("address", image.createApiCture());
        String content = freeMarkerRender(data, HTML);
        //System.out.println(content);
        createPdf(content, DEST);

    }

freemarkter()

 /**
     * freemarker渲染html
     */
    public static String freeMarkerRender(Map<String, Object> data, String htmlTmp) {
        Writer out = new StringWriter();
        try {
            // 获取模板,并设置编码方式
            Template template = freemarkerCfg.getTemplate(htmlTmp);
            template.setEncoding("UTF-8");
            // 合并数据模型与模板
            template.process(data, out); //将合并后的数据和模板写入到流中,这里使用的字符流
            out.flush();
            return out.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return null;
    }

createPdf()


    public static void createPdf(String content, String dest) throws IOException, DocumentException, DocumentException {
        com.demo.controller.ITextRenderer render = new ITextRenderer();
        // 如果携带图片则加上以下两行代码,将图片标签转换为Itext自己的图片对象,Base64ImgReplacedElementFactory为图片处理类
        render.getSharedContext().setReplacedElementFactory(new Base64ImgReplacedElementFactory());
        render.getSharedContext().getTextRenderer().setSmoothingThreshold(1);
        //设置字体
        ITextFontResolver fontResolver = render.getFontResolver();
        fontResolver.addFont(FONT_S, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        fontResolver.addFont(FONT, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        fontResolver.addFont(FONT_C, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        fontResolver.addFont(FONT_YH, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        fontResolver.addFont(ARIALUNI, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        // 解析html生成pdf
        render.setDocumentFromString(content);

        render.layout();
        render.createPDF(new FileOutputStream(dest));
        render.finishPDF();
    }

ftl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>签收单</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        body {
            font-family:'Arial Unicode MS','Microsoft YaHei UI';
            width: 100%;
            height: 100%;
            font-size: 10pt; /* 字体大小单位用 pt */
        }
        @media print {
            table {page-break-inside:avoid;}/*避免分页时内容被截断*/
        }
        @page {
            size: 210mm 297mm; /*A4大小*/
            margin: 20px 40px 20px 20px; /* 这里的margin太小了,底部的page看不到, margin border width单位用 px */

            @top-right {
                content: element(header-right)
            };
            @bottom-center {
                content: element(footer)
            }
        }
        #footer {
            position: running(footer);
        }
        #pages:before {
            content: counter(page);
        }
        #pages:after {
            content: counter(pages);
        }
        table {
            -fs-table-paginate: paginate;
            border-spacing: 0;
            border-collapse: collapse;
        }
        /*table, table td {*/
        /*    border-spacing: 0; !*去掉单元格间隙*!*/
        /*    border-collapse: collapse;  !*边框会合并为一个单一的边框*!*/
        /*}*/
        table tr{
            page-break-inside:avoid;
        }
        tr td {
            text-align:center;
            white-space:pre-line;
            word-wrap:break-word; /*内容居中自动换行*/
            word-break:break-all;
        }
        /*.tdBorder {
            border: 1px solid;
        }*/
        .none{
            width: 120px;
            height: 120px;
            background: #f447ff;
        }
    </style>
</head>
<body>
<table border="0" width="100%" style="table-layout:fixed;">
    <thead style="display:table-header-group;font-weight:bold">
        <tr>
            <td colspan="10" align="center"
                style="font-size:14pt;width: 100%;border: 0px;">签收单!!!每页都有的表头</td>
        </tr>
        <tr >
            <td class="tdBorder" align="center" style="border: 0px;font-size:12pt;
            padding-top: 5px;width:20px">
                ${order}
                <br/>
                ${orderId}
            </td>
            <td colspan="8"  text-align="left" dir="rtl" style="font-size:12pt;width:100px;border: 0px; ">
                尊敬的用户,您好 headerrrrrrrrrrrr
                <span style="display: block; -webkit-transform: rotate(-45deg); transform:rotate(-45deg);">good
                    !!</span>
            </td>
            <td align="right" style="font-size:12pt;border: 0px; ">
                here
            </td>
        </tr>
    <tr>
        <td colspan="10"><img src="https://img-blog.csdnimg.cn/2022010620391438313.png" width="600px" /></td>
    </tr>
    </thead>
    <tbody>
        <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>
        <tr>
            <th  width="10px" style="border: 0px;
            border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">序号21</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;transform: scaleY(0.5)">未签收数量</th>
        </tr>
        <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>
        <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>  <tr>
            <th  width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">序号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">订单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">箱单号</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">产品编码</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">电池型号</th>

            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">发货数量</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">Po Number &#10;/Line Number</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">备注</th>
            <th class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">未签收数量</th>
        </tr>
        <tr>
            <td class="tdBorder" width="10px" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格内容</td>
            <td class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格1234567890asdfghjklzxcvbnm1234567890asdfghjklzxcvbnm 内容</td>
            <td class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格内容</td>

            <td class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格1234567890asdfghjklzxcvbnm1234567890asdfghjklzxcvbnm 内容</td>
            <td class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格内容</td>
            <td class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格1234567890asdfghjklzxcvbnm1234567890asdfghjklzxcvbnm 内容</td>

            <td class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格内容</td>
            <td class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格1234567890asdfghjklzxcvbnm1234567890asdfghjklzxcvbnm 内容</td>
            <td class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格内容</td>
            <td class="tdBorder" style="border: 0px; border-bottom: 1px solid #000000;border-top: 1px solid #000000;">表格1234567890asdfghjklzxcvbnm1234567890asdfghjklzxcvbnm 内容</td>
        </tr>

    </tbody>

</table>
<div id="footer">
    <div style="text-align: center; width: 100%;height: 20px">Page
        <span id="pages"> of </span></div>
</div>
<footer>
    <table width="100%">
        <tr>
            <td class="tdBorder" width="10px">
                我是尾巴
            </td>
            <td class="tdBorder">
                <p class="none"></p>我是尾巴
            </td>
            <td class="tdBorder">我是尾巴。。。</td>

            <td class="tdBorder">我是尾巴。。。</td>
            <td class="tdBorder">我是尾巴。。。</td>
            <td class="tdBorder">我是尾巴。。。</td>

            <td class="tdBorder">我是尾巴。。。</td>
            <td class="tdBorder">我是尾巴。。。</td>
            <td class="tdBorder">我是尾巴。。。</td>
            <td class="tdBorder">我是尾巴。。。</td>
        </tr>
    </table>
</footer>


</body>
</html>

pom

  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version> 2.2.2.RELEASE</version>
    </parent>

    <dependencies>
        <!--web组件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--lombok简化实体类的get set方法-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- freemarker-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

        <!-- itextpdf,导出pdf核心架包 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.11</version>
        </dependency>
        <!-- itextpdf工具包,用来解析html生成pdf -->
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.11</version>
        </dependency>
        <!-- flying saucer,支持对CSS高级特性的解析 -->
<!--        <dependency>-->
<!--            <groupId>org.xhtmlrenderer</groupId>-->
<!--            <artifactId>flying-saucer-pdf</artifactId>-->
<!--            <version>9.1.6</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>net.sf.barcode4j</groupId>
            <artifactId>barcode4j-light</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>
        <!-- 支持css样式渲染 -->
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf-itext5</artifactId>
            <version>9.0.3</version>
        </dependency>

        <!-- 支持中文 -->
<!--        <dependency>-->
<!--            <groupId>com.itextpdf</groupId>-->
<!--            <artifactId>itext-asian</artifactId>-->
<!--            <version>5.2.0</version>-->
<!--        </dependency>-->
        <!--<dependency>
            <groupId>commons.codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.16</version>
        </dependency>-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
        </dependency>
    </dependencies>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值