PDF模板打印(中文折行,包括图片)
通过PDF模板,填充对象包括图片,生成pdf,包含中文折行以及图片插入
后台代码
生成pdf字节流文件
/**
* turnPhotoPdf:带附件图片的pdf
* @param object : 需要注入PDF模板的业务对象
* @param pdfFileName : PDF模板文件名称(此处需要针对不通对象使用不同模板所以做了部分修改)
* @param request :
* @param fileUploadList : PDF中显示图片为附件服务器中下载的图片集合
* @return byte[] : 填充后的pdf文件流转为字节数组
* @throws IOException
* @throws DocumentException
*/
public static byte[] turnPhotoPdf(Object object,String pdfFileName,List<FileUpload> fileUploadList, HttpServletRequest request) throws DocumentException, IOException{
//PDF模板的文件路径
String fileName=request.getServletContext().getRealPath("/")+"pdf\\pdftemplate\\"+pdfFileName;
PdfReader reader = new PdfReader(fileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfStamper ps = new PdfStamper(reader, bos);
ps.getReader().getFileLength();
ps.getReader().getAcroForm();
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
bf.setCompressionLevel(11);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
fontList.add(bf);
AcroFields fields = ps.getAcroFields();
fields.setSubstitutionFonts(fontList);
PDFUtil.fillData(fields, object);
//添加图片
for(int num=0;num<fileUploadList.size();num++){
if(fields.getFieldPositions("img"+(num+1)) == null){
break;
}
//获取PDF模板中图片域信息
int page = fields.getFieldPositions("img"+(num+1)).get(0).page;
Rectangle signReact = fields.getFieldPositions("img"+(num+1)).get(0).position;
float x = signReact.getLeft();
float y = signReact.getBottom();
//此处为FTP登录下载FTP服务器的图片(可以根据各自需要使用自己的图片获取方式)
FtpUtils ftp=new FtpUtils(SpringContextUtil.getMessage("ftpip"),Integer.valueOf(SpringContextUtil.getMessage("ftpport")),SpringContextUtil.getMessage("ftpuser"),SpringContextUtil.getMessage("ftppassword"));
InputStream is = ftp.getInputStream(fileUploadList.get(num).getPath(), fileUploadList.get(num).getRandomFileName());
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[1000];
int rc = 0;
while ((rc = is.read(buff, 0, 1000)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] in2b = swapStream.toByteArray();
//图片显示位置设置
Image image = Image.getInstance(in2b);
PdfContentByte under = ps.getOverContent(page);
image.scaleToFit(signReact.getWidth(),signReact.getHeight());
float imageWidth = image.getPlainWidth();
float imageLeft = (signReact.getWidth() - imageWidth)/2;
image.setAbsolutePosition(x+imageLeft,y);
under.addImage(image);
//此处为本人业务系统中某一字段的数据处理(可以忽略)
fields.setField("description"+(num+1), fileUploadList.get(num).getDescription());
}
//true为可编辑,false为PDF还可以修改.
ps.setFormFlattening(true);
ps.close();
return bos.toByteArray();
}
/**
* 填充模板
*/
public static void fillData(AcroFields fields, Object data)throws IOException, DocumentException {
String[] fieldNames = getFiledName(data);
for(int j=0 ; j<fieldNames.length ; j++){
String name = fieldNames[j];
Object value = getFieldValueByName(name,data);
if(value != null){
fields.setField(name, fields.getField(name)+value.toString());
}
}
}
private static String[] getFiledName(Object o){
Field[] fields=o.getClass().getDeclaredFields();
String[] fieldNames=new String[fields.length];
for(int i=0;i<fields.length;i++){
fieldNames[i]=fields[i].getName();
}
return fieldNames;
}
private static Object getFieldValueByName(String fieldName, Object o) {
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getter = "get" + firstLetter + fieldName.substring(1);
Method method = o.getClass().getMethod(getter, new Class[] {});
Object value = method.invoke(o, new Object[] {});
return value;
} catch (Exception e) {
return null;
}
}
/**
* PDF文件流整合(此处为引用其他网站信息,没做更改可直接使用)
* @param streamOfPDFFiles : pdf文件流集合
* @param outputStream
* @param paginate
*/
public static void concatPDFs(List<InputStream> streamOfPDFFiles,
OutputStream outputStream, boolean paginate) {
Document document = new Document();
try {
List<InputStream> pdfs = streamOfPDFFiles;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();
// Create Readers for the pdfs.
while (iteratorPDFs.hasNext()) {
InputStream pdf = iteratorPDFs.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages += pdfReader.getNumberOfPages();
}
// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
// data
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Loop through the PDF files and add to the output.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create a new page in the target for each source page.
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
page = writer.getImportedPage(pdfReader,
pageOfCurrentReaderPDF);
cb.addTemplate(page, 0, 0);
// Code for pagination.
if (paginate) {
cb.beginText();
cb.setFontAndSize(bf, 9);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
+ currentPageNumber + " of " + totalPages, 520,
5, 0);
cb.endText();
}
}
pageOfCurrentReaderPDF = 0;
}
outputStream.flush();
document.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document.isOpen())
document.close();
try {
if (outputStream != null)
outputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
模板制作
将word文件转为pdf文件,通过Adobe Acrobat DC软件打开PDF然后点击准备表单生成对应文本域,此处文本域还可自行添加
这里一定要注意的是如果是图片插入的话需要将图片域添加进去之后将图片域的通用属性表单域设置为隐藏,否则图片会显示到图片域图层的下边.