示例模版:
示例导出:
核心代码:
package com.yonyou.dms.framework.service.pdf;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.AcroFields.FieldPosition;
import com.itextpdf.text.pdf.Barcode39;
import com.itextpdf.text.pdf.BarcodeQRCode;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.yonyou.dms.framework.service.pdf.domain.PDFTableDto;
/**
* @ClassName: PDFTemplateExport
* @Description: TODO
* @Author: [email protected]
* @Date: 2017年8月26日
*/
public class PDFTemplateExport {
private static final Logger logger = LoggerFactory.getLogger(PDFTemplateExport.class);
private String templatePdfPath;
private String fontName = "simsun.ttc,1";
public PDFTemplateExport(String templatePdfPath) {
this.templatePdfPath = templatePdfPath;
}
public PDFTemplateExport(String templatePdfPath, String fontName) {
this.templatePdfPath = templatePdfPath;
this.fontName = fontName;
}
/**
* 根据模版导出PDF文档
* @param os 输出流
* @param textFields 文本字段
* @param barcodeFields 条码字段
* @param qrcodeFields 二维码字段
* @param tableFields 表格字段
* @throws Exception
*/
public void export(OutputStream os, Map textFields, Map barcodeFields, Map qrcodeFields,Map tableFields) throws Exception {
//读取模版
PdfReader reader = new PdfReader(templatePdfPath);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfStamper ps = new PdfStamper(reader, bos);
//使用中文字体
BaseFont bf = BaseFont.createFont(getFontPath(fontName), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
ArrayList fontList = new ArrayList ();
fontList.add(bf);
AcroFields s = ps.getAcroFields();
s.setSubstitutionFonts(fontList);
//遍历表单字段
for (Map.Entry entry : textFields.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
s.setFieldProperty(key, "textfont", bf, null);
s.setField(key, getBlank(value));
}
//遍历条码字段
for (Map.Entry entry : barcodeFields.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// 获取属性的类型
if(value != null && s.getField(key) != null){
//获取位置(左上右下)
FieldPosition fieldPosition = s.getFieldPositions(key).get(0);
//绘制条码
Barcode39 barcode39 = new Barcode39();
//字号
barcode39.setSize(12);
//条码高度
barcode39.setBarHeight(30);
//条码与数字间距
barcode39.setBaseline(10);
//条码值
barcode39.setCode(value.toString());
barcode39.setStartStopText(false);
barcode39.setExtended(true);
//绘制在第一页
PdfContentByte cb = ps.getOverContent(1);
//生成条码图片
Image image128 = barcode39.createImageWithBarcode(cb, null, null);
//左边距(居中处理)
float marginLeft = (fieldPosition.position.getRight() - fieldPosition.position.getLeft() - image128.getWidth()) / 2;
//条码位置
image128.setAbsolutePosition(fieldPosition.position.getLeft() + marginLeft, fieldPosition.position.getBottom());
//加入条码
cb.addImage(image128);
}
}
//遍历二维码字段
for (Map.Entry entry : qrcodeFields.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// 获取属性的类型
if(value != null && s.getField(key) != null){
//获取位置(左上右下)
FieldPosition fieldPosition = s.getFieldPositions(key).get(0);
//绘制二维码
float width = fieldPosition.position.getRight() - fieldPosition.position.getLeft();
BarcodeQRCode pdf417 = new BarcodeQRCode(value.toString(), (int)width, (int)width, null);
//生成二维码图像
Image image128 = pdf417.getImage();
//绘制在第一页
PdfContentByte cb = ps.getOverContent(1);
//左边距(居中处理)
float marginLeft = (fieldPosition.position.getRight() - fieldPosition.position.getLeft() - image128.getWidth()) / 2;
//条码位置
image128.setAbsolutePosition(fieldPosition.position.getLeft() + marginLeft, fieldPosition.position.getBottom());
//加入条码
cb.addImage(image128);
}
}
//遍历表格字段
Font keyfont = new Font(bf, 8, Font.BOLD);// 设置字体大小
Font textfont = new Font(bf, 8, Font.NORMAL);// 设置字体大小
for (Map.Entry entry : tableFields.entrySet()) {
String key = entry.getKey();
PDFTableDto tableDto = entry.getValue();
// 获取属性的类型
if(tableDto != null && tableDto.getColFields() != null && s.getField(key) != null){
//获取位置(左上右下)
FieldPosition fieldPosition = s.getFieldPositions(key).get(0);
float width = fieldPosition.position.getRight() - fieldPosition.position.getLeft();
//创建表格
String[] thread = tableDto.getColNames() != null ? tableDto.getColNames().split(",") : tableDto.getColFields().split(",");
PdfPTable table = new PdfPTable(thread.length);
try{
table.setTotalWidth(width);
table.setLockedWidth(true);
table.setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setBorder(1);
}catch(Exception e){
e.printStackTrace();
}
//创建表头
for (String col : thread) {
table.addCell(createCell(col, keyfont, Element.ALIGN_CENTER));
}
//创建表体
String[] fields = tableDto.getColFields().split(",");
List
调用方法:
package com.yonyou.dms.framework.service.pdf.impl;
import java.io.File;
import java.io.OutputStream;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.yonyou.dms.framework.service.pdf.PDFTemplateExport;
import com.yonyou.dms.framework.service.pdf.PdfGenerator;
import com.yonyou.dms.framework.service.pdf.domain.PDFGeneratorDto;
import com.yonyou.dms.framework.service.pdf.domain.PDFTableDto;
import com.yonyou.dms.function.exception.ServiceBizException;
import com.yonyou.dms.function.exception.UtilException;
import com.yonyou.dms.function.utils.common.CommonUtils;
import com.yonyou.dms.function.utils.common.StringUtils;
import com.yonyou.dms.function.utils.io.IOUtils;
@Component
public class PdfGeneratorDefaultImpl implements PdfGenerator {
// 定义日志接口
private static final Logger logger = LoggerFactory.getLogger(PdfGeneratorDefaultImpl.class);
/**
* 生成Pdf文件到下载输出流
* @param generator
* @param request
* @param response
*/
@Override
public void generatePdf(@SuppressWarnings("rawtypes") PDFGeneratorDto generator, HttpServletRequest request, HttpServletResponse response) {
// 如果Data中没有数据,则返回错误
if (generator == null || StringUtils.isNullOrEmpty(generator.getTempPath()) || CommonUtils.isNullOrEmpty(generator.getTextFields())) {
throw new ServiceBizException("No Pdf Data !");
}
OutputStream outputStream = null;
PDFTemplateExport pdfExport = null;
try {
// 初始化输出流
String fileName = StringUtils.getString(generator.getFileName(), UUID.randomUUID());
outputStream = initOutputStream(request, response, fileName, generator.isOnlineView());
// 初始化模版
String fontPath = StringUtils.getString(generator.getFontPath());
String tempPath = StringUtils.getString(generator.getTempPath());
String rootDir = request.getSession().getServletContext().getRealPath("/");
tempPath = rootDir + "assets" + File.separator + "pdf" + File.separator + tempPath;
if (StringUtils.isNullOrEmpty(fontPath)) {
pdfExport = new PDFTemplateExport(tempPath);
} else {
pdfExport = new PDFTemplateExport(tempPath, fontPath);
}
// 写入数据
Map textFields = generator.getTextFields();
Map barcodeFields = generator.getBarcodeFields();
Map qrcodeFields = generator.getQrcodeFields();
Map tableFields = generator.getTableFields();
pdfExport.export(outputStream, textFields, barcodeFields, qrcodeFields, tableFields);
} catch (Exception exception) {
logger.warn(exception.getMessage(), exception);
throw new ServiceBizException(exception.getMessage(), exception);
} finally {
IOUtils.closeStream(outputStream);
}
}
/**
* 初始化输出流
* @param request
* @param response
* @param fileName
* @param isOnLine
* @return
* @throws UtilException
*/
private OutputStream initOutputStream(HttpServletRequest request, HttpServletResponse response, String fileName, boolean isOnLine) throws UtilException {
try {
// 中文文件名兼容性调整
String enableFileName = "";
String agent = (String) request.getHeader("USER-AGENT");
if (agent != null && agent.indexOf("like Gecko") != -1) {// IE11
enableFileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
}else if (agent != null && agent.indexOf("MSIE") == -1) {// FF
enableFileName = "=?UTF-8?B?" + (new String(Base64.encodeBase64(fileName.getBytes("UTF-8")))) + "?=";
} else { // IE
enableFileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
}
// 输出文件流
response.reset(); // 非常重要
if (isOnLine) { // 在线打开方式
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=" + enableFileName);
} else { // 纯下载方式
response.setContentType("application/x-msdownload");
response.setHeader("Content-Disposition", "attachment; filename=" + enableFileName);
}
return response.getOutputStream();
} catch (Exception e) {
throw new UtilException("pdf 流初始化失败", e);
}
}
}
package com.yonyou.dms.framework.service.pdf.domain;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* PDF模版信息
* @author XiongRx
* @date 2017年7月19日
*/
public class PDFGeneratorDto {
private String tempPath;
private String fontPath;
private Map textFields = new HashMap();
private Map barcodeFields = new HashMap();
private Map qrcodeFields = new HashMap();
private Map tableFields = new HashMap();
private String fileName;
private boolean onlineView = false;
public String getTempPath() {
return tempPath;
}
public void setTempPath(String tempPath) {
this.tempPath = tempPath;
}
public String getFontPath() {
return fontPath;
}
public void setFontPath(String fontPath) {
this.fontPath = fontPath;
}
public Map getTextFields() {
return textFields;
}
public void setTextFields(Map textFields) {
this.textFields = textFields;
}
public Map getBarcodeFields() {
return barcodeFields;
}
public void setBarcodeFields(Map barcodeFields) {
this.barcodeFields = barcodeFields;
}
public Map getQrcodeFields() {
return qrcodeFields;
}
public void setQrcodeFields(Map qrcodeFields) {
this.qrcodeFields = qrcodeFields;
}
public Map getTableFields() {
return tableFields;
}
public void setTableFields(Map tableFields) {
this.tableFields = tableFields;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public boolean isOnlineView() {
return onlineView;
}
public void setOnlineView(boolean onlineView) {
this.onlineView = onlineView;
}
}
package com.yonyou.dms.framework.service.pdf.domain;
import java.util.List;
import java.util.Map;
/**
* PDF表格信息
* @author XiongRx
* @date 2017年7月19日
*/
public class PDFTableDto {
private String colNames;
private String colFields;
private List> dataList;
public String getColNames() {
return colNames;
}
public void setColNames(String colNames) {
this.colNames = colNames;
}
public String getColFields() {
return colFields;
}
public void setColFields(String colFields) {
this.colFields = colFields;
}
public List> getDataList() {
return dataList;
}
public void setDataList(List> dataList) {
this.dataList = dataList;
}
}
相关JAR包:
com.itextpdf
itextpdf
5.5.10
com.itextpdf
itext-asian
5.2.0
还是写点备注吧:
这个代码重要的不是模版也不是条码(满大街都是),是在模版里设置条码和表格的位置。
实现按格式导出只需要核心代码就够了,写了个调用工具类是因为核心方法的参数较多,不方便调用,再者写了个实体类后续有新增需求也好维护,加新属性就好了,不会影响已有的调用。
http://rensanning.iteye.com/blog/1538689
附上很全的参考资料,并表示感谢。
已上传实例
https://download.csdn.net/download/ruixue0117/21420308