利用Java Itext生成PDF文件并导出,实现效果如下:
PDFUtil.java
package com.jeeplus.modules.order.util; import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
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.PdfWriter;
import com.jeeplus.common.utils.Encodes;
import com.jeeplus.common.utils.StringUtils;
import com.jeeplus.modules.order.entity.OrderHeader;
import com.jeeplus.modules.order.entity.OrderLine;
import com.jeeplus.modules.order.service.PDFService;
import com.jeeplus.modules.sys.utils.UserUtils; public class PDFUtil { /**
*
* @param exhibitionName 展会名称
* @param orders 订单
* @param REMITTANCE_UNIT 收款单位
* @param REMITTANCE_BANK 收款银行
* @param REMITTANCE_ACCOUNT 收款账号
* @param SEAL_PICTURE_NAME 印章名称默认为深圳中智兴
* @param payUrl 系统网址
* @param response
* @throws Exception author:xiaofei.xian 日期:2018年5月30日 上午11:29:57
*/
public static void createPDF(String exhibitionName, List<OrderHeader> orders, String REMITTANCE_UNIT, String REMITTANCE_BANK,
String REMITTANCE_ACCOUNT, String SEAL_PICTURE_NAME, String payUrl, HttpServletResponse response) throws Exception {
// 生成PDF
Document document = new Document(PageSize.A4);
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);
Font fontMoney = new Font(bfChinese, 13, Font.BOLD, BaseColor.RED);
Font BlodFont = new Font(bfChinese, 12, Font.BOLD, BaseColor.BLACK); // 写入器
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
// 只读
writer.setEncryption(null, null, PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);
// 通过PDF页面事件模式添加文字水印功能
writer.setPageEvent(new TextWaterMarkPdfPageEvent(REMITTANCE_UNIT)); // 添加页脚功能
document.open();
PdfPTable pdfPTable = new PdfPTable(1);
PdfFooterEvent footerTable = new PdfFooterEvent(pdfPTable, payUrl);
footerTable.setTableFooter(writer);
document.add(pdfPTable); // 添加PDF属性
document.open();
Paragraph pph1 = new Paragraph("预租确认回执", new Font(bfChinese, 20, Font.BOLD, BaseColor.BLACK));
pph1.setAlignment(Element.ALIGN_CENTER);
pph1.setSpacingAfter(10);
pph1.setSpacingBefore(5);
document.add(pph1);
// 6列的表.
PdfPTable table = new PdfPTable(6);
table.setTotalWidth(500);
table.setLockedWidth(true);
table.setHorizontalAlignment(Element.ALIGN_CENTER); // 第一行
PdfPCell cell1 = new PdfPCell(new Phrase("展会名称:" + exhibitionName, fontChinese));
cell1.setColspan(6);
table.addCell(cell1); StringBuffer boothNums = new StringBuffer();
for (OrderHeader orderHeader : orders) {
// 获取订单信息
boothNums.append(orderHeader.getExName() + ",");
} // 第二行
PdfPCell cell2 = new PdfPCell(new Phrase("展位编号:" + boothNums.toString().subSequence(0, boothNums.length() - 1), fontChinese));
cell2.setColspan(6);
table.addCell(cell2); // 第三行
PdfPCell cell3 = new PdfPCell(new Phrase("下单人:" + UserUtils.get(orders.get(0).getCreateBy()).getName(), fontChinese));
cell3.setColspan(6);
cell3.setHorizontalAlignment(Element.ALIGN_RIGHT);
table.addCell(cell3); // 第四行
PdfPCell cell4_1 = new PdfPCell(new Phrase("名称", fontChinese));
PdfPCell cell4_2 = new PdfPCell(new Phrase("规格", fontChinese));
PdfPCell cell4_3 = new PdfPCell(new Phrase("单价", fontChinese));
PdfPCell cell4_4 = new PdfPCell(new Phrase("押金", fontChinese));
PdfPCell cell4_5 = new PdfPCell(new Phrase("数量", fontChinese));
PdfPCell cell4_6 = new PdfPCell(new Phrase("小计", fontChinese));
table.addCell(cell4_1);
table.addCell(cell4_2);
table.addCell(cell4_3);
table.addCell(cell4_4);
table.addCell(cell4_5);
table.addCell(cell4_6); BigDecimal total = BigDecimal.ZERO; List<OrderLine> orderLines = new ArrayList<OrderLine>();
for (OrderHeader orderHeader : orders) {
orderLines = orderHeader.getOrderLines();
for (OrderLine orderLine : orderLines) {
cell4_1 = new PdfPCell(new Phrase(orderLine.getGoodsName(), fontChinese));
cell4_2 = new PdfPCell(new Phrase(orderLine.getSpecifications(), fontChinese));
cell4_3 = new PdfPCell(new Phrase(String.valueOf(orderLine.getUnitPrice()), fontChinese)); DecimalFormat df1 = new DecimalFormat("0.00");
String str = df1.format(orderLine.getForegift().multiply(orderLine.getBuyNum().subtract(orderLine.getEditForegiftPrice())));
cell4_4 = new PdfPCell(new Phrase(str, fontChinese));
cell4_5 = new PdfPCell(new Phrase(String.valueOf(orderLine.getBuyNum()), fontChinese));
cell4_6 =
new PdfPCell(new Phrase(String.valueOf((orderLine.getUnitPrice().add(orderLine.getForegift())).multiply(orderLine.getBuyNum())
.subtract(orderLine.getEditFeePrice().subtract(orderLine.getEditForegiftPrice()))), fontChinese));
total = total.add((orderLine.getUnitPrice().add(orderLine.getForegift())).multiply(orderLine.getBuyNum())
.subtract(orderLine.getEditFeePrice().subtract(orderLine.getEditForegiftPrice())));
table.addCell(cell4_1);
table.addCell(cell4_2);
table.addCell(cell4_3);
table.addCell(cell4_4);
table.addCell(cell4_5);
table.addCell(cell4_6);
}
} // 第六行
PdfPCell cell6 = new PdfPCell(new Phrase("总计:" + total, fontMoney));
cell6.setColspan(6);
table.addCell(cell6); // 第七行
PdfPCell cell7_1 = new PdfPCell(new Phrase("收款单位:", fontChinese));
PdfPCell cell7_2 = new PdfPCell(new Phrase(REMITTANCE_UNIT, fontChinese));
cell7_1.setHorizontalAlignment(Element.ALIGN_LEFT);
cell7_2.setHorizontalAlignment(Element.ALIGN_LEFT);
cell7_1.setColspan(2);
cell7_2.setColspan(4); table.addCell(cell7_1);
table.addCell(cell7_2); cell7_1 = new PdfPCell(new Phrase("开户行:", fontChinese));
cell7_2 = new PdfPCell(new Phrase(REMITTANCE_BANK, fontChinese));
cell7_1.setHorizontalAlignment(Element.ALIGN_LEFT);
cell7_2.setHorizontalAlignment(Element.ALIGN_LEFT);
cell7_1.setColspan(2);
cell7_2.setColspan(4); table.addCell(cell7_1);
table.addCell(cell7_2); cell7_1 = new PdfPCell(new Phrase("账号:", fontChinese));
cell7_2 = new PdfPCell(new Phrase(REMITTANCE_ACCOUNT, fontMoney));
cell7_1.setHorizontalAlignment(Element.ALIGN_LEFT);
cell7_2.setHorizontalAlignment(Element.ALIGN_LEFT);
cell7_1.setColspan(2);
cell7_2.setColspan(4); table.addCell(cell7_1);
table.addCell(cell7_2); // 第十行
PdfPCell cell10 = new PdfPCell(new Phrase(REMITTANCE_UNIT, fontChinese));
cell10.setHorizontalAlignment(Element.ALIGN_RIGHT);
cell10.setColspan(6);
table.addCell(cell10); document.add(table); // 默认为深圳中智兴
if (StringUtils.isEmpty(SEAL_PICTURE_NAME)) {
SEAL_PICTURE_NAME = "zzx_seal.png";
}
// 读入并设置印章图片
URL resource = PDFService.class.getResource("/sealimg/" + SEAL_PICTURE_NAME);
Image image = Image.getInstance(resource);
image.setScaleToFitLineWhenOverflow(true);
image.setAlignment(Element.ALIGN_RIGHT);
float x = table.getTotalWidth();
float y = 750 - table.getTotalHeight();
while (y < 0) {
y = 750 - (table.getTotalHeight() - 750);
}
image.setAbsolutePosition(x - 60, y);
image.scaleAbsolute(100, 100);
PdfContentByte pcb = writer.getDirectContentUnder();
pcb.addImage(image);
document.add(image);
document.add(Chunk.NEWLINE); // 特别提醒
Paragraph paragraphRemark = new Paragraph();
Font remarkFont = new Font(bfChinese, 10, Font.NORMAL);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
paragraphRemark.add(new Chunk("特别提醒:", BlodFont));
paragraphRemark.add(Chunk.NEWLINE);
paragraphRemark.add(new Chunk("1.您的汇款识别码为", remarkFont));
paragraphRemark.add(new Chunk(orders.get(0).getRemitCode(), fontMoney));
paragraphRemark.add(new Chunk("。请将此识别码填写到汇款单【附言】栏内(仅填写此识别码),如未填写会影响订单确认时间。", remarkFont));
paragraphRemark.add(Chunk.NEWLINE);
paragraphRemark.add(Chunk.NEWLINE);
paragraphRemark.add(new Chunk("2.请将待支付款项在", remarkFont));
paragraphRemark.add(new Chunk(sdf.format(orders.get(0).getCancelDate()), fontMoney));
paragraphRemark.add(new Chunk("前通过银行汇到以上指定账号,请您尽快汇清款项,逾期订单将自动取消,汇款后请等待确认收款,到账周期一般为1-3个工作日。", remarkFont));
paragraphRemark.add(Chunk.NEWLINE);
paragraphRemark.add(Chunk.NEWLINE);
paragraphRemark.add(new Chunk("4.汇款金额请与应付金额保持一致,请勿多汇款或者少汇款。", remarkFont));
paragraphRemark.add(Chunk.NEWLINE);
document.add(paragraphRemark); sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
pph1 = new Paragraph("打印日期:" + sdf.format(new Date()), fontChinese);
pph1.setAlignment(Element.ALIGN_RIGHT);
pph1.setSpacingBefore(20);
document.add(pph1);
response.setContentType("application/pdf; charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + Encodes.urlEncode("预租确认回执") + ".pdf");
document.close();
writer.close();
OutputStream out = response.getOutputStream();
out.flush();
response.flushBuffer();
} }
水印事件TextWaterMarkPdfPageEvent.java
package com.jeeplus.modules.order.util; import java.io.IOException;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter; /**
* PDF 水印事件
*
* @author xiaofei.xian 日期:2018年5月30日 上午11:25:18
*/
public class TextWaterMarkPdfPageEvent extends PdfPageEventHelper { private String waterMarkText; public TextWaterMarkPdfPageEvent(String waterMarkText) {
this.waterMarkText = waterMarkText;
} @Override
public void onEndPage(PdfWriter writer, Document document) {
try {
float pageWidth = document.right() + document.left();// 获取pdf内容正文页面宽度
float pageHeight = document.top() + document.bottom();// 获取pdf内容正文页面高度
// 设置水印字体格式
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font waterMarkFont = new Font(base, 15, Font.BOLD, new BaseColor(230, 230, 230));
PdfContentByte waterMarkPdfContent = writer.getDirectContentUnder();
Phrase phrase = new Phrase(waterMarkText, waterMarkFont);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.25f, pageHeight * 0.2f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.25f, pageHeight * 0.5f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.25f, pageHeight * 0.8f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.65f, pageHeight * 0.2f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.65f, pageHeight * 0.5f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.65f, pageHeight * 0.8f, 45);
} catch (DocumentException de) {
de.printStackTrace();
} catch (IOException de) {
de.printStackTrace();
}
}
}
页脚事件PdfFooterEvent.java
package com.jeeplus.modules.order.util; import java.io.IOException;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter; /**
* PDF 页眉事件
*
* @author xiaofei.xian 日期:2018年5月30日 上午11:25:00
*/
public class PdfFooterEvent extends PdfPageEventHelper { public static PdfPTable footer; public static String webUrl; public PdfFooterEvent(PdfPTable footer, String webUrl) {
PdfFooterEvent.footer = footer;
PdfFooterEvent.webUrl = webUrl;
} @Override
public void onEndPage(PdfWriter writer, Document document) {
// 把页脚表格定位
footer.writeSelectedRows(0, -1, 38, 30, writer.getDirectContent());
} /**
* 页脚是文字
*
* @param writer
* @param songti09
* @throws IOException
* @throws DocumentException
*/
public void setTableFooter(PdfWriter writer) throws DocumentException, IOException {
PdfPTable table = new PdfPTable(1);
table.setTotalWidth(520f);
PdfPCell cell = new PdfPCell();
cell.setBorder(1);
String string =
"本回执仅做财务付款申请凭证,它用无效 网址:" + webUrl;
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font FontChinese = new Font(bfChinese, 10, Font.NORMAL);
FontChinese.setColor(new BaseColor(150, 150, 150));
Paragraph p = new Paragraph(string, FontChinese);
cell.setPaddingLeft(10f);
cell.setPaddingTop(-2f);
cell.addElement(p);
table.addCell(cell);
PdfFooterEvent event = new PdfFooterEvent(table, webUrl);
writer.setPageEvent(event);
}
}