| | |
| | | package cn.flightfeather.supervision.common.pdf |
| | | |
| | | import org.apache.poi.util.Units |
| | | import org.apache.poi.xwpf.usermodel.XWPFDocument |
| | | import org.apache.poi.xwpf.usermodel.XWPFParagraph |
| | | import java.io.File |
| | | import java.io.FileInputStream |
| | | import java.io.FileOutputStream |
| | | import java.io.IOException |
| | | import com.itextpdf.html2pdf.ConverterProperties |
| | | import com.itextpdf.html2pdf.HtmlConverter |
| | | import com.itextpdf.layout.font.FontProvider |
| | | import com.itextpdf.text.Element |
| | | import com.itextpdf.text.Font |
| | | import com.itextpdf.text.FontFactory |
| | | import com.itextpdf.text.pdf.BaseFont |
| | | import com.itextpdf.text.pdf.PdfReader |
| | | import com.itextpdf.text.pdf.PdfStamper |
| | | import org.apache.pdfbox.pdmodel.PDDocument |
| | | import org.apache.pdfbox.rendering.PDFRenderer |
| | | import org.fit.pdfdom.PDFDomTree |
| | | import org.fit.pdfdom.PDFDomTreeConfig |
| | | import org.xhtmlrenderer.pdf.ITextRenderer |
| | | import java.io.* |
| | | import javax.imageio.ImageIO |
| | | import javax.xml.parsers.ParserConfigurationException |
| | | |
| | | |
| | | object PdfUtil { |
| | | |
| | | fun generateContract(dynamicParam: DynamicParam): String { |
| | | val src = dynamicParam.templatePath+dynamicParam.templateName |
| | | val out = dynamicParam.outPath + dynamicParam.outName |
| | | private const val FONT1 = "/font/STSONG.TTF" |
| | | private const val FONT2 = "font/msyhbd.ttc" |
| | | private const val FONT3 = "font/msyhl.ttc" |
| | | |
| | | val inputStream = FileInputStream(File(src)) |
| | | val xwpfDocument = XWPFDocument(inputStream) |
| | | |
| | | replace(xwpfDocument, dynamicParam.param) |
| | | |
| | | output(xwpfDocument, out) |
| | | |
| | | return out |
| | | @Throws(IOException::class, ParserConfigurationException::class) |
| | | fun parseWithPdfDomTree(`is`: InputStream?, startPage: Int, endPage: Int, config: PDFDomTreeConfig?): String? { |
| | | val pdf: PDDocument = PDDocument.load(`is`) |
| | | val parser = PDFDomTree(config) |
| | | parser.startPage = startPage |
| | | parser.endPage = endPage |
| | | val output: Writer = StringWriter() |
| | | parser.writeText(pdf, output) |
| | | pdf.close() |
| | | return output.toString() |
| | | } |
| | | |
| | | /** |
| | | * 替换段落中指定的文本 |
| | | */ |
| | | fun replace(doc:XWPFDocument, params:Map<String, Any>) { |
| | | try { |
| | | setContent(doc.paragraphs, params) |
| | | fun htmlToPdf(content: String): ByteArray { |
| | | |
| | | for (tab in doc.tables) { |
| | | for (row in tab.rows) { |
| | | for (cell in row.tableCells) { |
| | | //注意,getParagraphs一定不能漏掉 |
| | | //因为一个表格里面可能会有多个需要替换的文字 |
| | | //如果没有这个步骤那么文字会替换不了 |
| | | setContent(cell.paragraphs, params) |
| | | val p = ConverterProperties() |
| | | |
| | | p.fontProvider = FontProvider().apply { |
| | | addFont(FONT1) |
| | | } |
| | | val outputStream = ByteArrayOutputStream() |
| | | HtmlConverter.convertToPdf(content, outputStream, p) |
| | | val inputStream = ByteArrayInputStream(outputStream.toByteArray()) |
| | | val reader = PdfReader(inputStream) |
| | | val output = ByteArrayOutputStream() |
| | | val stamper = PdfStamper(reader, output) |
| | | |
| | | val totalPages = reader.numberOfPages |
| | | val font = BaseFont.createFont(FONT1, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED) |
| | | for (i in 1..totalPages) { |
| | | // 读取第i页内容 |
| | | val page = stamper.getOverContent(i) |
| | | |
| | | val pageSize = reader.getPageSize(i) |
| | | page.run { |
| | | beginText() |
| | | setFontAndSize(font, 12F) |
| | | showTextAligned(Element.ALIGN_CENTER, "第 ${i} 页", pageSize.width / 2, 20F, 0F) |
| | | endText() |
| | | } |
| | | } |
| | | } |
| | | } catch (e: IOException) { |
| | | e.printStackTrace() |
| | | } |
| | | stamper.close() |
| | | reader.close() |
| | | |
| | | // val render = ITextRenderer() |
| | | // render.fontResolver.adF |
| | | |
| | | return output.toByteArray() |
| | | |
| | | |
| | | } |
| | | |
| | | private fun setContent(paragraphs: List<XWPFParagraph>, params: Map<String, Any>) { |
| | | for (p in paragraphs) { |
| | | for (r in p.runs) { |
| | | //需要替换的文本 |
| | | val text = r.getText(0) |
| | | //替换指定的文本 |
| | | for (key in params.keys) { |
| | | if (text != null && text == key) { |
| | | //替换的时候要注意,setText是有两个参数的 |
| | | //第一个是替换的文本,第二个是从哪里开始替换 |
| | | //0是替换全部,如果不设置那么默认就是从原文字 |
| | | //结尾开始追加 |
| | | val v = params[key] |
| | | when (v) { |
| | | is String -> r.setText(v, 0) |
| | | is File -> { |
| | | val input = FileInputStream(v) |
| | | val pic = r.addPicture(input, XWPFDocument.PICTURE_TYPE_JPEG, v.name, Units.toEMU(40.0), Units.toEMU(40.0)) |
| | | fun pdfToPic(bytes: ByteArray): List<ByteArray> { |
| | | val picOutput = mutableListOf<ByteArrayOutputStream>() |
| | | |
| | | input.close() |
| | | val doc = PDDocument.load(bytes) |
| | | val renderer = PDFRenderer(doc) |
| | | val pageCount = doc.numberOfPages |
| | | for (i in 0 until pageCount) { |
| | | val output = ByteArrayOutputStream() |
| | | picOutput.add(output) |
| | | // dpi,图片像素点,dpi越高图片体积越大,216很清晰,105体积稳定 |
| | | val image = renderer.renderImageWithDPI(i, 216f) |
| | | // 格式为JPG |
| | | ImageIO.write(image, "jpg", output) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | fun output(doc: XWPFDocument, outSrc: String) { |
| | | doc.write(FileOutputStream(outSrc)) |
| | | doc.close() |
| | | return picOutput.map { it.toByteArray() } |
| | | } |
| | | } |