package com.zudp.common.core.utils.pdf;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.*;
/**
* 根据PDF模板生成具体内容PDF
*/
public class PDFUtils {
private static final Logger log = LoggerFactory.getLogger(PDFUtils.class);
/**
* @param fields
* @param data
* @throws IOException
* @throws DocumentException
*/
private static void fillData(AcroFields fields, Map<String, String> data) throws IOException, DocumentException {
List<String> keys = new ArrayList<String>();
Map<String, AcroFields.Item> formFields = fields.getFields();
for (String key : data.keySet()) {
if (formFields.containsKey(key)) {
String value = data.get(key);
// 为字段赋值,注意字段名称是区分大小写的
fields.setField(key, value);
keys.add(key);
}
}
Iterator<String> itemsKey = formFields.keySet().iterator();
while (itemsKey.hasNext()) {
String itemKey = itemsKey.next();
if (!keys.contains(itemKey)) {
fields.setField(itemKey, " ");
}
}
}
/**
* @param templatePdfPath 模板pdf路径
* @param generatePdf 生成pdf路径
* @param imagePath 图片路径
* @param fitWidth 图片宽
* @param fitHeight 图片高
* @param data 数据
*/
public MultipartFile getPDFMultipartFile(String templatePdfPath, String generatePdf,String imageFiledName, String imagePath,
Float fitWidth, Float fitHeight,Map<String, String> data) {
ByteArrayOutputStream bos = null;
InputStream inputStream = null ;
MultipartFile file = null ;
try {
PdfReader reader = new PdfReader(templatePdfPath);
// 将要生成的目标PDF文件名称
bos = new ByteArrayOutputStream();
// 使用中文字体
PdfStamper ps = new PdfStamper(reader, bos);
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
// 取出报表模板中的所有字段
fontList.add(bf);
AcroFields fields = ps.getAcroFields();
fields.setSubstitutionFonts(fontList);
//设置图片
if (StringUtils.isNotBlank(imagePath)) {
// 通过域名获取所在页和坐标,左下角为起点
int pageno = fields.getFieldPositions(imageFiledName).get(0).page;
Rectangle signrect = fields.getFieldPositions(imageFiledName).get(0).position;
float x = signrect.getLeft();
float y = signrect.getBottom();
// 读图片
Image image = Image.getInstance(imagePath);
// 获取操作的页面
PdfContentByte under = ps.getOverContent(pageno);
// 这里控制图片的大小
//image.scaleToFit(signrect.getWidth(), signrect.getHeight());
image.scaleToFit(fitWidth, fitHeight);
// 添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
//移除图片的路径,要不然会把路径也设置上去
data.remove(imageFiledName);
}
// 必须要调用这个,否则文档不会生成的 如果为false那么生成的PDF文件还能编辑,一定要设为true
fillData(fields, data);
ps.setFormFlattening(true);
ps.close();
byte[] testFile = bos.toByteArray();
inputStream = new ByteArrayInputStream(testFile);
try {
file = new MockMultipartFile(generatePdf, generatePdf, ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
} catch (IOException e) {
log.error(e.getMessage());
}
} catch (Exception e) {
log.error(e.getMessage());
} finally {
if(inputStream != null ){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
log.error(e.getMessage());
}
}
}
return file;
}
/**
* 生成到本地
* @param templatePdfPath 模板pdf路径
* @param generatePdfPath 生成pdf路径
* @param data 数据
*/
public String generatePDF(String templatePdfPath, String generatePdfPath, Map<String, String> data) {
OutputStream fos = null;
ByteArrayOutputStream bos = null;
try {
PdfReader reader = new PdfReader(templatePdfPath);
// 将要生成的目标PDF文件名称
bos = new ByteArrayOutputStream();
// 使用中文字体
PdfStamper ps = new PdfStamper(reader, bos);
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
// 取出报表模板中的所有字段
fontList.add(bf);
AcroFields fields = ps.getAcroFields();
fields.setSubstitutionFonts(fontList);
// 必须要调用这个,否则文档不会生成的 如果为false那么生成的PDF文件还能编辑,一定要设为true
fillData(fields, data);
ps.setFormFlattening(true);
ps.close();
fos = new FileOutputStream(generatePdfPath);
fos.write(bos.toByteArray());
fos.flush();
return generatePdfPath;
} catch (Exception e) {
log.error(e.getMessage());
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
log.error(e.getMessage());
}
}
}
return null;
}
/**
* 获取生成文件的MultipartFile
* @param templatePdfPath
* @param generatePdf
* @param data
* @return
*/
public MultipartFile getPDFMultipartFile(String templatePdfPath, String generatePdf, Map<String, String> data) {
ByteArrayOutputStream bos = null;
MultipartFile file = null ;
InputStream inputStream = null ;
try {
PdfReader reader = new PdfReader(templatePdfPath);
// 将要生成的目标PDF文件名称
bos = new ByteArrayOutputStream();
// 使用中文字体
PdfStamper ps = new PdfStamper(reader, bos);
String url = "/home/data/pdf_template/simfang.ttf";
BaseFont bf = BaseFont.createFont(url, BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
// 可能存在的问题:adober的版本不同造成中文不能显示,或者其他原因导致字体失效。该方法不是很稳妥
// BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
// 取出报表模板中的所有字段
fontList.add(bf);
AcroFields fields = ps.getAcroFields();
fields.setSubstitutionFonts(fontList);
// 必须要调用这个,否则文档不会生成的 如果为false那么生成的PDF文件还能编辑,一定要设为true
fillData(fields, data);
ps.setFormFlattening(true);
ps.close();
byte[] testFile = bos.toByteArray();
inputStream = new ByteArrayInputStream(testFile);
try {
file = new MockMultipartFile(generatePdf, generatePdf, ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
} catch (IOException e) {
log.error(e.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(inputStream != null ){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return file;
}
}