java原装代码完成pdf在线预览和pdf打印及下载

网友投稿 256 2023-06-15


java原装代码完成pdf在线预览和pdf打印及下载

前提准备:

1. 项目中至少需要引入的jar包,注意版本:

a) core-renderer.jar

b) freemarker-2.3.16.jar

c) iText-2.0.8.jar

d) iTextAsian.jar

上代码:

注释: 此类为自定义的Tag类的基类,在action中怎么放的数据,在ftl中就怎么取数据,简洁明了。

1. 自定义Tag类的基类

/**

* 通用的生成pdf预览和生成打印的html文件

*

* @author xg君

*

*/

public abstract class PDFTag extends BodyTagSupport {

private static final long serialVersionUID = 1L;

// 标签属性变量

private String json = "";

private String tempDir = "";

// 非标签属性变量

private Map rootMap = new HashMap();

private String templateStr = null;

private String freemarkereConfigurationBeanName = null;

private String fileName = null;

private String basePath = null;

private String fileEncoding = "utf-8";

@Override

public int doStartTag() throws JspException {

setConfigParams();

WebApplicationContext application = WebApplicationContextUtils.getWebApplicationContext(pageContext

.getServletContext());

doServiceStart();

String ctx = (String) pageContext.getAttribute("ctx");

rootMap.put("ctx", ctx);

Map map = parseJSON2Map(json);

rootMap.putAll(map);

if (freemarkereConfigurationBeanName == null) {

try {

throw new CstuException("FreemarkereConfigurationBeanName不能为空!");

} catch (CstuException e) {

e.printStackTrace();

}

}

Configuration cptFreemarkereConfiguration = (Configuration) application

.getBean(freemarkereConfigurationBeanName);

try {

if (templateStr == null) {

throw new CstuException("模板文件不能为空!");

}

Template template = cptFreemarkereConfiguration.getTemplate(templateStr);

if (basePath == null) {

throw new CstuException("文件的基本路径(父路径)不能为空!");

}

File htmlPath = new File(tempDir + File.separator + basePath);

if (!htmlPath.exists()) {

htmlPath.mkdirs();

}

if (fileName == null) {

throw new CstuException("生成的html文件名不能为空!");

}

File htmlFile = new File(htmlPath, File.separator + fileName);

if (!htmlFile.exists()) {

htmlFile.createNewFile();

}

BufferedWriter out = new BufferedWriter(

new OutputStreamWriter(new FileOutputStream(htmlFile), fileEncoding));

template.process(rootMap, out);

out.flush();

doServiceDoing();

// 显示在页面

template.process(rootMap, pageContext.getResponse().getWriter());

} catch (Exception e) {

e.printStackTrace();

}

doServiceEnd();

return SKIP_BODY;

}

/**

* 配置基础参数,如

*/

public abstract void setConfigParams();

/**

* 业务处理方法-开始 填充数据

*

* @return

*/

public abstract void doServiceStart();

/**

* 业务处理方法-执行中 备用,可空实现,若rootMap中存在双份数据则可在此处填充判断条件

*

* @return

*/

public abstract void doServiceDoing();

/**

* 业务处理方法-结束 清空rootMap并调用垃圾回收,也可空实现

*

* @return

*/

public abstract void doServiceEnd();

/**

* 将元素放入rootMap中

*/

public void putKV(String key, Object value) {

rootMap.put(key, value);

}

/**

* 将map放入rootMap中

*

* @param m

*/

public void putMap(Map m) {

rootMap.putAll(m);

}

public void clear() {

rootMap.clear();

rootMap = null;

}

/**

* 移除元素

*

* @param key

* @return

*/

public Object remove(String key) {

return rootMap.remove(key);

}

public static Map parseJSON2Map(String jsonStr) {

Map map = new HashMap();

JSONObject json = JSONObject.fromObject(jsonStr);

for (Object k : json.keySet()) {

Object v = json.get(k);

if (v instanceof JSONArray) {

List> list = new ArrayList>();

Iterator it = ((JSONArray) v).iterator();

while (it.hasNext()) {

JSONObject json2 = it.next();

list.add(parseJSON2Map(json2.toString()));

}

map.put(k.toString(), list);

} else {

map.put(k.toString(), v);

}

}

return map;

}

public String getJson() {

return json;

}

public void setJson(String json) {

this.json = json;

}

public String getTempDir() {

return tempDir;

}

public void setTempDir(String tempDir) {

this.tempDir = tempDir;

}

public String getTemplateStr() {

return templateStr;

}

public void setTemplateStr(String templateStr) {

this.templateStr = templateStr;

}

public String getFreemarkereConfigurationBeanName() {

return freemarkereConfigurationBeanName;

}

public void setFreemarkereConfigurationBeanName(String freemarkereConfigurationBeanName) {

this.freemarkereConfigurationBeanName = freemarkereConfigurationBeanName;

}

public String getFileName() {

return fileName;

}

public void setFileName(String fileName) {

this.fileName = fileName;

}

public String getBasePath() {

return basePath;

}

public void setBasePath(String basePath) {

this.basePath = basePath;

}

public String getFileEncoding() {

return fileEncoding;

}

public void setFileEncoding(String fileEncoding) {

this.fileEncoding = fileEncoding;

}

}

注释: setConfigParams方法是用于调用接口定义的配置参数的方法,如:templateStr,basePath等,doServiceStart,doServiceDoing和doServiceEnd等方法用于处理业务逻辑,比如我的需求是做出合同在一个页面显示,要分页,要加水印,但生成的pdf样式与预览的是不同的,所以我加了一个doServiceDoing中给rootMap添加判断条件,这样就能一个flt文件作出两种效果(预览和打印),当然如果预览和打印要一样的效果,doServiceDoing方法可以空实现。这四个方法总结一下就是:

1. setConfigParams : 配置参数

2. doServiceStart : 填充数据/条件

3. doServiceDoing : 填充数据/条件,到这里是个分界线,此方法之前,rootMap数据先进入html再进入浏览器(预览),此方法之后,rootMap数据会再次进入html文件,结束,所以此处可写判断

4. doServiceEnd : 可有可无,我还是写上了,万一哪天的数据集太大,此处便可以在数据填充完后,清理掉,节省内存空间

2. PDFTag的子类

/**

* 用户自定义PDFTag类

*

* @author xg君

*

*/

public class ViewPDFTag extends PDFTag {

private static final long serialVersionUID = 4528567203497016087L;

private String prjNature = "";

private String bookName = "";

private String prjCode = "";

/**

* 用户自定义的配置参数

*/

public PDFConfigurationInterface pDFConfigurationInterface = new PDFConfigurationInterface() {

@Override

public void configTemplateStr() {

// 横,纵向

if (prjNature.equalsIgnoreCase("2") || prjNature.equalsIgnoreCase("1")) {

setTemplateStr("wj-project-print.ftl");

}

}

@Override

public void configFreemarkereConfigurationBeanName() {

setFreemarkereConfigurationBeanName("cptFreemarkereConfiguration");

}

@Override

public void configFileName() {

// 填入html文件

setFileName(prjCode + ".html");

}

@Override

public void configFileEncoding() {

// 默认utf-8

}

@Override

public void configBasePath() {

setBasePath("html_pdf");

}

};

@Override

public void doServiceStart() {

putKV("prjNature", prjNature);

putKV("bookName", bookName);

putKV("flag", "0");

}

@Override

public void doServiceDoing() {

putKV("flag", "1");

}

@Override

public void doServiceEnd() {

clear();

System.gc();

}

public String getPrjNature() {

return prjNature;

}

public void setPrjNature(String prjNature) {

this.prjNature = prjNature;

}

public String getBookName() {

return bookName;

}

public void setBookName(String bookName) {

this.bookName = bookName;

}

public String getPrjCode() {

return prjCode;

}

public void setPrjCode(String prjCode) {

this.prjCode = prjCode;

}

@Override

public void setConfigParams() {

pDFConfigurationInterface.configTemplateStr(); pDFConfigurationInterface.configFreemarkereConfigurationBeanName();

pDFConfigurationInterface.configFileName();

pDFConfigurationInterface.configBasePath();

pDFConfigurationInterface.configFileEncoding();

}

}

注释: PDFConfigurationInterface 是自定义的标签参数配置接口,子类必须定义一个该接口的实现类的成员变量或定义一个成员变量内部类,并在setConfigParams方法中调用使其生效。

子类的成员变量接收在tld文件中配置的属性。

3. 自定义的标签参数配置接口

/**

* PdfTag类的配置

*

* @author xg君

*

*/

public interface PDFConfigurationInterface {

/**

* 设置模板名称

*/

void configTemplateStr();

/**

* 设置配置的FreemarkereConfigurationBean的名称

*/

void configFreemarkereConfigurationBeanName();

/**

* 设置生成的html文件名称

*/

void configFileName();

/**

* 设置生成的html文件的基本路径(父目录)

*/

void configBasePath();

/**

* 设置文件编码,默认utf-8

*/

void configFileEncoding();

}

4. 自定义异常类

/**

* 自定义异常类

*

* @author Administrator

*

*/

public class CstuException extends Exception {

private static final long serialVersionUID = 4266461814747405870L;

public CstuException(String msg) {

super(msg);

}

}

5. tld文件配置

print com.iris.taglib.web.PreviewPDFTag

JSP

json

true

true

prjNature

true

true

bookName

true

true

tempDir

true

true

prjCode

true

true

6. action

/**

* 处理PDF导出

*

*/

@Namespace("/export")

@Results({ @Result(name = "exceltemplate", location = "/WEB-INF/content/pdf/export-pdf.jsp"),

@Result(name = "exprotPdf2", location = "/WEB-INF/content/project/project/export/export-pdf2.jsp") })

public class ExportPdfAction extends ActionSupport {

private static final long serialVersionUID = -5454188364706173477L;

@Value("${tempDir}")

private String tempDir;

@Value("${pdfFont}")

private String pdfFont;

@Value("${staticResRootDir}")

private String staticResRootDir;

@Value("${staticResRootDir2}")

private String staticResRootDir2;

@Value("${WaterMarkImgDir}")

private String waterMarkImgDir;

@Autowired

private ProjectService projectService;

@Autowired

private PersonService personService;

@Autowired

private ConstDictionaryService constDictionaryService;

@Autowired

private FdPlanDetailService fdPlanDetailService;

@Autowired

private ServiceFactory serviceFactory;

@Action("exprotPdf2")

public String exprotPdf2() {

String prjCode = Struts2Utils.getParameter("prjCode");

prjCode = Struts2Utils.decodeDesString(prjCode);

Project project = projectService.getProjectById(Long.parseLong(prjCode));

Map baseInfo = new HashMap();

baseInfo.put("tempDir", tempDir);

// 项目编号

baseInfo.put("prjCode", prjCode);

// 项目类型

String prjNature = project.getPrjNature();

baseInfo.put("prjNature", prjNature);

// 水印名称格式:watermark+"-"+prjNature

baseInfo.put("waterMarkImg", waterMarkImgDir + File.separator + "watermark-" + prjNature + ".png");

// 负责人

Person person = personService.getPerson(project.getPsnCode());

String zhName = person.getZhName();

baseInfo.put("zhName", addStr(9, "
", zhName));

// 项目编号

String prjNo = project.getPrjNo();

baseInfo.put("prjNo", prjNo);

// 项目来源

ConstDictionary cd = constDictionaryService.findCdByCategoryCode("project_from", project.getGrantNo());

String project_from = cd.getzh_cn_caption();

baseInfo.put("project_from", addStr(9, "
", project_from));

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

// 起止年限

String startDate = sdf.format(project.getStartDate());

String endDate = sdf.format(project.getEndDate());

String startEndDate = startDate + "~" + endDate;

cshiitQbaseInfo.put("startEndDate", startEndDate);

// 项目类别--资助类别

String grantName = project.getGrantName();

baseInfo.put("grantName", addStr(9, "
", grantName));

// 合同金额

String totalAmt = project.getTotalAmt().toString();

BigDecimal totalAmt_ = checkNumber(totalAmt);

baseInfo.put("totalAmt", totalAmt_.toString());

// 项目名称

String zhTitle = project.getZhTitle();

baseInfo.put("zhTitle", addStr(38, "
", zhTitle));

List> ps = null;

try {

ps = getMembers(project.getPrjXml());

} catch (Exception e) {

e.printStackTrace();

}

String bookName = "";

// 判断项目类型

Map itemMap = new HashMap();

if (prjNature.equalsIgnoreCase("1")) {

bookName = "第一份合同";

// 获取fdPlanDetail

List> list = fdPlanDetailService.getFdPlanDetailsByPrjCode(Long.parseLong(prjCode));

// test

/*

* Map test = new HashMap(); test.put("itemValue", "6");

* test.put("itemName", "差旅费"); test.put("remark", "xxxxx"); list.add(test);

*/

for (Map m : list) {

String key = (String) m.get("ITEMNAME");

BigDecimal itemValue = (BigDecimal) m.get("ITEMVALUE");

BigDecimal proportion = new BigDecimal(0.00);

if (itemValue != null && totalAmt_.compareTo(new BigDecimal("0.00")) != 0) {

proportion = itemValue.divide(totalAmt_, 6, BigDecimal.ROUND_HALF_EVEN);

}

if (itemValue == null) {

itemValue = new BigDecimal("0.00");

}

proportion = checkNumber(proportion.toString());

Map data = new HashMap();

// 添加比例

data.put("proportion", proportion.toString());

// 检测金额规范

BigDecimal amt = checkNumber(itemValue.toString());

data.put("itemValue", amt.toString());

// remark

String remark = (String) m.get("REAMRK");

data.put("remark", remark == null ? "" : remark);

itemMap.put(key, data);

}

} else if (prjNature.equalsIgnoreCase("2")) {

bookName = "第二份合同";

}

Map map = new HashMap();

map.put("baseInfo", baseInfo);

map.put("projectMember", ps);

map.put("itemMap", itemMap);

map.put("psCount", ps.size());

map.put("psSum", 25 - ps.size());

String json = JSONObject.fromObject(map).toString();

Struts2Utils.getRequest().setAttribute("jsonData", json);

Struts2Utils.getRequest().setAttribute("prjNature", prjNature);

Struts2Utils.getRequest().setAttribute("bookName", bookName)http://;

Struts2Utils.getRequest().setAttribute("tempDir", tempDir);

Struts2Utils.getRequest().setAttribute("prjCode", prjCode);

return "exprotPdf2";

}

public List> getMembers(String xmlData) throws Exception {

List> list = new ArrayList>();

Document doc = DocumentHelper.parseText(xmlData);

Node ps = doc.selectSingleNode("/data/project/persons");

List psList = ps.selectNodes("person");

String totalAmt = doc.selectSingleNode("/data/project/basic_info/total_amt").getText();

for (Node person : psList) {

Map map = new HashMap();

Node fund_proportion = person.selectSingleNode("fund_proportion");

String fund_proportion_text = "";

if (fund_proportion == null) {

map.put("proportion", "0.00");

map.put("fpAmt", "0.00");

} else {

fund_proportion_text = fund_proportion.getText();

BigDecimal fp = new BigDecimal(fund_proportion_text);

fp = fp.multiply(new BigDecimal("0.01"));

fp = checkNumber(fp.toString());

map.put("proportion", fp.toString());

BigDecimal fdAmt_ = fp.multiply(new BigDecimal(totalAmt));

fdAmt_ = checkNumber(fdAmt_.toString());

map.put("fpAmt", fdAmt_.toString());

}

Node psn_name = person.selectSingleNode("psn_name");

String psn_name_text = psn_name.getText();

map.put("zhName_p", addStr(9, "
", psn_name_text));

Node psn_work = person.selectSingleNode("psn_work");

String psn_work_text = "";

if (psn_work != null) {

psn_work_text = psn_work.getText();

}

map.put("work", addStr(9, "
", psn_work_text));

Node dept_code_name = person.selectSingleNode("dept_code_name");

String dept_code_name_text = "";

if (dept_code_name != null) {

dept_code_name_text = dept_code_name.getText();

}

map.put("deptName", addStr(9, "
", dept_code_name_text));

Node psn_type_name = person.selectSingleNode("psn_type_name");

String psn_type_name_text = "";

if (psn_type_name != null) {

psn_type_name_text = psn_type_name.getText();

}

map.put("psnTypeName", psn_type_name_text);

list.add(map);

}

return list;

}

/**

* 为字符串添加指定字符

*

* @param num

* @param splitStr

* @param str

* @return

*/

public String addStr(int num, String splitStr, String str) {

StringBuffer sb = new StringBuffer();

String temp = str;

int len = str.length();

while (len > 0) {

if (len < num) {

num = len;

}

sb.append(temp.substring(0, num)).append(splitStr);

temp = temp.substring(num);

len = temp.length();

}

return sb.toString();

}

/**

* 两个数字/英文

*

* @param str

* @param num

* @return 最终索引

*/

public static int getEndIndex(String str, double num) {

int idx = 0;

int count = 0;

double val = 0.00;

// 判断是否是英文/数字

for (int i = 0; i < str.length(); i++) {

if ((str.charAt(i) >= 'A' && str.charAt(i) <= 'Z') || (str.charAt(i) >= 'a' && str.charAt(i) <= 'z')

|| Character.isDigit(str.charAt(i))) {

val += 0.50;

} else {

val += 1.00;

}

count = i + 1;

if (val >= num) {

idx = i;

break;

}

}

if (idx == 0) {

idx = count;

}

return idx;

}

/**

* 下载pdf文件

*

* @return

*/

@Action("downLoad")

public String downLoad() {

String prjCode = Struts2Utils.getParameter("prjCode");

String basePath = "html_pdf";

Project project = projectService.getProjectById(Long.parseLong(prjCode));

String zhTitle = project.getZhTitle();

FileOutputStream fos = null;

// html

File htmlFile = new File(tempDir + File.separator + basePath + File.separator + prjCode + ".html");

String pdfPath = tempDir + File.separator + basePath + File.separator + zhTitle + ".pdf";

try {

fos = new FileOutputStream(pdfPath);

String url = htmlFile.toURI().toURL().toString();

ITextRenderer renderer = new ITextRenderer();

renderer.setDocument(url);

ITextFontResolver fontResolver = renderer.getFontResolver();

fontResolver.addFont(pdfFont + File.separator + "SimSun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

renderer.layout();

renderer.createPDF(fos);

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

if (fos != null) {

fos.close();

}

} catch (IOException e) {

e.printStackTrace();

}

}

// 添加水印

String wartermark = "";

if (project.getPrjNature().equalsIgnoreCase("1")) {

// 横向

wartermark = "CTGU横向科研项目立项通知书";

} else if (project.getPrjNature().equalsIgnoreCase("2")) {

// 纵向

wartermark = "CTGU纵向科研项目立项通知书";

}

String wm_pdf = tempDir + File.separator + "wm_" + project.getZhTitle() + ".pdf";

try {

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(wm_pdf));

waterMark(bos, pdfPath, wartermark, staticResRootDir2 + File.separator + waterMarkImgDir + File.separator

+ "watermark-" + project.getPrjNature() + ".png");

} catch (Exception e2) {

e2.printStackTrace();

}

// 拿到pdf

File pdfFile = new File(wm_pdf);

BufferedOutputStream out = null;

FileInputStream in = null;

try {

in = new FileInputStream(pdfFile);

HttpServletResponse response = Struts2Utils.getResponse();

response.reset();

String fileName = zhTitle + ".pdf";

String fileName2 = URLEncoder.encode(fileName, "UTF-8");

String agent = Struts2Utils.getRequest().getHeader("USER-AGENT");

// IE

if (null != agent && -1 != agent.indexOf("MSIE")) {

fileName2 = new String(fileName.getBytes("GBK"), "ISO8859-1");

} else if (null != agent && -1 != agent.indexOf("Mozilla")) {

fileName2 = new String(fileName.getBytes("UTF-8"), "ISO8859-1");

}

response.setCharacterEncoding("UTF-8");

response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName2 + "\"");

response.setContentType(FileContentTypes.getContentType(zhTitle + ".pdf"));

out = new BufferedOutputStream(response.getOutputStream());

byte[] buffer = new byte[16 * 1024];

int len = 0;

while ((len = in.read(buffer)) > 0) {

out.write(buffer, 0, len);

}

out.flush();

} catch (Exception e) {

e.printStackTrace();

} finally {

if (out != null) {

try {

out.close();

} catch (IOException e1) {

e1.printStackTrace();

}

try {

in.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

// 清理残留文件

// if (htmlFile.exists()) {

// htmlFile.delete();

// }

File temp_file = new File(pdfPath);

if (temp_file.exists()) {

temp_file.delete();

}

if (pdfFile.exists()) {

pdfFile.delete();

}

return null;

}

public BigDecimal checkNumber(String number) {

// 初始化为6位小数

DecimalFormat df = new DecimalFormat("0.000000");

String num = df.format(Double.parseDouble(number));

BigDecimal bd = new BigDecimal(num);

String val = bd.toString();

val = val.replaceAll("^(0+)", "");

val = val.replaceAll("(0+)$", "");

int idx = val.indexOf(".");

int len = val.substring(idx + 1).length();

if (len < 2) {

if (len == 0 && idx == 0) {

bd = new BigDecimal("0.00");

} else {

bd = new BigDecimal(val).setScale(2);

}

} else {

bd = new BigDecimal(val).setScale(len);

}

return bd;

}

private String replaceStr(String str, String reVal) {

Pattern pattern = Pattern.compile("^" + reVal + "+|" + reVal + "+$");

Matcher matcher = pattern.matcher(str);

return matcher.replaceAll("");

}

/**

* 添加水印

*/

private void waterMark(BufferedOutputStream bos, String input, String waterMarkName, String imagePath) {

try {

PdfReader reader = new PdfReader(input);

PdfStamper stamper = new PdfStamper(reader, bos);

int total = reader.getNumberOfPages() + 1;

PdfContentByte content;

BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

PdfGState gs = new PdfGState();

for (int i = 1; i < total; i++) {

content = stamper.getOverContent(i);// 在内容上方加水印

content.setGState(gs);

content.beginText();

Image image = Image.getInstance(imagePath);

image.setAbsolutePosition(-30, 200);

image.scalePercent(80);

content.addImage(image);

content.endText();

}

stamper.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

7. ftl文件(模板文件)

......

预览效果:

打印效果:


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Node连接mysql数据库方法介绍
下一篇:spring四种依赖注入方式的详细介绍
相关文章

 发表评论

暂时没有评论,来抢沙发吧~