admin 管理员组文章数量: 887019
因为公司业务需要,利用一个ftl模板生成word在转为pdf。然后发现印章图片在页底那边显示不全,没有如文字一般自动换到下一页去。例如如下:
最后折腾了半天,在网上试了各种办法。最后只能通过 java提取PDF文字坐标。来算出印章图片坐标,根据坐标y轴测出印章图片极限安全位置y坐标,如果大于该坐标y则表示该印章图片显示在同一页且图片显示完全,如果小于该坐标则表示图片显示不全,这时候只能换一种逻辑,写两个ftl模板,一个只显示印章图片前的数据,一个只显示印章图片之后的(包括印章),最后将两个pdf合并为一个。这种办法不太好,太麻烦了。。但是业务紧急,暂时也找不到更好的办法去处理。凑合凑合吧。
java提取PDF文字坐标 可以参考https://blog.csdn/sinat_29957455/article/details/78759654
我对他的方法稍微做了点改进以更适应我的需求。
1.如何生成ftl模板
之后在重命名xml为ftl文件就行。
2.pdf提取关键字Util工具类
①通过定义一个类实现RenderListener,可以通过里面的几个方法来操作PDF中的文字和图片
package cn.xxxmon.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.awt.geom.RectangularShape;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
public class TestRenderListener implements RenderListener {
//用来存放文字的矩形
List<Rectangle2D.Float> rectText = new ArrayList<Rectangle2D.Float>();
//用来存放文字
List<String> textList = new ArrayList<String>();
//用来存放文字的y坐标
List<Float> listY = new ArrayList<Float>();
//用来存放每一行文字的坐标位置
List<Map<String,Rectangle2D.Float>> rows_text_rect = new ArrayList<>();
//PDF文件的路径
protected String filepath = null;
public TestRenderListener() {
}
//step 2,遇到"BT"执行
@Override
public void beginTextBlock() {
// TODO Auto-generated method stub
}
//step 3
/**
* 文字主要处理方法
*/
@Override
public void renderText(TextRenderInfo renderInfo) {
//获取文字的下面的矩形
//Rectangle2D.Float rectBase = renderInfo.getBaseline().getBoundingRectange();
String text = renderInfo.getText();
if(text.length() > 0){
RectangularShape rectBase = renderInfo.getBaseline().getBoundingRectange();
//获取文字下面的矩形
Rectangle2D.Float rectAscen = renderInfo.getAscentLine().getBoundingRectange();
//计算出文字的边框矩形
float leftX = (float) rectBase.getMinX();
float leftY = (float) rectBase.getMinY()-1;
float rightX = (float) rectAscen.getMaxX();
float rightY = (float) rectAscen.getMaxY()+1;
Rectangle2D.Float rect = new Rectangle2D.Float(leftX, leftY, rightX - leftX, rightY - leftY);
if(listY.contains(rect.y)){
int index = listY.indexOf(rect.y);
float tempx = rect.x > rectText.get(index).x ? rectText.get(index).x : rect.x;
rectText.set(index,new Rectangle2D.Float(tempx,rect.y,rect.width + rectText.get(index).width,rect.height));
textList.set(index,textList.get(index) + text);
}else{
rectText.add(rect);
textList.add(text);
listY.add(rect.y);
}
Map<String,Rectangle2D.Float> map = new HashMap<>();
map.put(text,rect);
rows_text_rect.add(map);
}
}
//step 4(最后执行的,只执行一次),遇到“ET”执行
@Override
public void endTextBlock() {
// TODO Auto-generated method stub
}
//step 1(图片处理方法)
@Override
public void renderImage(ImageRenderInfo renderInfo) {
}
}
②pdf提取关键字Util工具类 (下载一个itextpdf jar包 我的是5.5.13版本) 不要急着复制,因为这个工具类是一段一段提取pdf文字坐标 所以为了知道自己的关键词在不在他的词分析器里需要进行测试。测试完知道自己的关键词后 放开当中部分一段注释的逻辑代码并修改,则就可以返回唯一的关键词坐标y。
package cn.xxxmon.util;
import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class WordInPdfLocatonUtil {
/**
*
* @param keyWord 关键词
* @param pdfPath pdf 文件路径
* @return 关键词所在该页pdf坐标y轴
*/
public static Float getY(String keyWord,String pdfPath) {
Float locationY = null; //关键词坐标y轴
PdfReader reader = null;
FileOutputStream out =null;
try {
reader = new PdfReader(pdfPath);
//新建一个PDF解析对象
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
//包含了PDF页面的信息,作为处理的对象
out = new FileOutputStream("d:test.pdf");
PdfStamper stamper = new PdfStamper(reader, out);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
//新建一个ImageRenderListener对象,该对象实现了RenderListener接口,作为处理PDF的主要类
TestRenderListener listener = new TestRenderListener();
//解析PDF,并处理里面的文字
parser.processContent(i, listener);
//获取文字的矩形边框
List<Rectangle2D.Float> rectText = listener.rectText;
List<String> textList = listener.textList;
List<Float> listY = listener.listY;
List<Map<String, Rectangle2D.Float>> list_text = listener.rows_text_rect;
for (int k = 0; k < list_text.size(); k++) {
Map<String, Rectangle2D.Float> map = list_text.get(k);
for (Map.Entry<String, Rectangle2D.Float> entry : map.entrySet()) {
//判断与关键词是否相等,为了防止出现关键词没找到,缩小关键词范围匹配
// if(entry.getKey().indexOf(keyWord)==-1){
// if(keyWord.length()>=3){
// String firstKeyWord=keyWord;
// keyWord=keyWord.substring(0,2);// “此函”
// if(entry.getKey().indexOf(keyWord)==-1){
// keyWord = firstKeyWord.substring(1,3);//“函告”
// }
// }
// }
// if (entry.getKey().indexOf(keyWord) > -1) {//只打印并返回关键词坐标
float y = entry.getValue().y;
locationY = y ;
System.out.println(entry.getKey() + "---" + y);
// }
}
}
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("文件未找到");
} catch (DocumentException e) {
e.printStackTrace();
}finally {
try {
reader.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return locationY;
}
public static void main(String[] args) {
getY("此函告","D:\\hzresources\\test.pdf");
}
}
如果注释不放开打印的是如下所有字段与y轴坐标。
如果注释放开就只返回关键词对应坐标y,打印的就是第二幅图。
3.合并pdf工具类 (itext-2.1.7.jar)
package cn.xxxmon.util;
import java.io.FileOutputStream;
import java.io.IOException;
import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
public class PdfMergeUtil {
public static void main(String[] args) {
String[] files = {"D:\\hzresources\\4928F159-4A62-B018-402A-AED4C578AD17.pdf",
"D:\\hzresources\\4928F159-4A62-B018-402A-AED4C578AD17pic.pdf"};
mergePdfFiles(files, "D:\\hzresources\\merge.pdf");
}
/**
*
* @param files 合並pdf文件数组
* @param newfile 合并后pdf路径
* @return 成功返回true, 否則返回false
*/
public static boolean mergePdfFiles(String[] files, String newfile) {
boolean retValue = false;
Document document = null;
FileOutputStream out =null;
try {
document = new Document(new PdfReader(files[0]).getPageSize(1));
out = new FileOutputStream(newfile);
PdfCopy copy = new PdfCopy(document, out);
document.open();
for (int i = 0; i < files.length; i++) {
PdfReader reader = new PdfReader(files[i]);
int n = reader.getNumberOfPages();
for (int j = 1; j <= n; j++) {
document.newPage();
PdfImportedPage page = copy.getImportedPage(reader, j);
copy.addPage(page);
}
}
retValue = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
document.close();
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return retValue;
}
}
最后只要合并pdf就可以了,这样就完美的解决了图片在页底显示不全的问题。
版权声明:本文标题:利用.ftl模板生成word之后再转pdf发现 填充的印章图片显示不全,没有自动移到下一页处理办法 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1726309716h934175.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论