java原裝代碼完成pdf在線預(yù)覽和pdf打印及下載
前提準(zhǔn)備:
1. 項(xiàng)目中至少需要引入的jar包,注意版本:
a) core-renderer.jar
b) freemarker-2.3.16.jar
c) iText-2.0.8.jar
d) iTextAsian.jar
上代碼:
注釋: 此類為自定義的Tag類的基類,在action中怎么放的數(shù)據(jù),在ftl中就怎么取數(shù)據(jù),簡(jiǎn)潔明了。
1. 自定義Tag類的基類
/**
* 通用的生成pdf預(yù)覽和生成打印的html文件
*
* @author xg君
*
*/
public abstract class PDFTag extends BodyTagSupport {
private static final long serialVersionUID = 1L;
// 標(biāo)簽屬性變量
private String json = "";
private String tempDir = "";
// 非標(biāo)簽屬性變量
private Map<String, Object> rootMap = new HashMap<String, Object>();
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<String, Object> 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();
// 顯示在頁(yè)面
template.process(rootMap, pageContext.getResponse().getWriter());
} catch (Exception e) {
e.printStackTrace();
}
doServiceEnd();
return SKIP_BODY;
}
/**
* 配置基礎(chǔ)參數(shù),如
*/
public abstract void setConfigParams();
/**
* 業(yè)務(wù)處理方法-開(kāi)始 填充數(shù)據(jù)
*
* @return
*/
public abstract void doServiceStart();
/**
* 業(yè)務(wù)處理方法-執(zhí)行中 備用,可空實(shí)現(xiàn),若rootMap中存在雙份數(shù)據(jù)則可在此處填充判斷條件
*
* @return
*/
public abstract void doServiceDoing();
/**
* 業(yè)務(wù)處理方法-結(jié)束 清空rootMap并調(diào)用垃圾回收,也可空實(shí)現(xiàn)
*
* @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<String, Object> parseJSON2Map(String jsonStr) {
Map<String, Object> map = new HashMap<String, Object>();
JSONObject json = JSONObject.fromObject(jsonStr);
for (Object k : json.keySet()) {
Object v = json.get(k);
if (v instanceof JSONArray) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Iterator<JSONObject> 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方法是用于調(diào)用接口定義的配置參數(shù)的方法,如:templateStr,basePath等,doServiceStart,doServiceDoing和doServiceEnd等方法用于處理業(yè)務(wù)邏輯,比如我的需求是做出合同在一個(gè)頁(yè)面顯示,要分頁(yè),要加水印,但生成的pdf樣式與預(yù)覽的是不同的,所以我加了一個(gè)doServiceDoing中給rootMap添加判斷條件,這樣就能一個(gè)flt文件作出兩種效果(預(yù)覽和打印),當(dāng)然如果預(yù)覽和打印要一樣的效果,doServiceDoing方法可以空實(shí)現(xiàn)。這四個(gè)方法總結(jié)一下就是:
1. setConfigParams : 配置參數(shù)
2. doServiceStart : 填充數(shù)據(jù)/條件
3. doServiceDoing : 填充數(shù)據(jù)/條件,到這里是個(gè)分界線,此方法之前,rootMap數(shù)據(jù)先進(jìn)入html再進(jìn)入瀏覽器(預(yù)覽),此方法之后,rootMap數(shù)據(jù)會(huì)再次進(jìn)入html文件,結(jié)束,所以此處可寫(xiě)判斷
4. doServiceEnd : 可有可無(wú),我還是寫(xiě)上了,萬(wàn)一哪天的數(shù)據(jù)集太大,此處便可以在數(shù)據(jù)填充完后,清理掉,節(jié)省內(nèi)存空間
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 = "";
/**
* 用戶自定義的配置參數(shù)
*/
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() {
// 默認(rèn)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 是自定義的標(biāo)簽參數(shù)配置接口,子類必須定義一個(gè)該接口的實(shí)現(xiàn)類的成員變量或定義一個(gè)成員變量?jī)?nèi)部類,并在setConfigParams方法中調(diào)用使其生效。
子類的成員變量接收在tld文件中配置的屬性。
3. 自定義的標(biāo)簽參數(shù)配置接口
/**
* PdfTag類的配置
*
* @author xg君
*
*/
public interface PDFConfigurationInterface {
/**
* 設(shè)置模板名稱
*/
void configTemplateStr();
/**
* 設(shè)置配置的FreemarkereConfigurationBean的名稱
*/
void configFreemarkereConfigurationBeanName();
/**
* 設(shè)置生成的html文件名稱
*/
void configFileName();
/**
* 設(shè)置生成的html文件的基本路徑(父目錄)
*/
void configBasePath();
/**
* 設(shè)置文件編碼,默認(rèn)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文件配置
<tag> <name>print</name> <tagclass>com.iris.taglib.web.PreviewPDFTag</tagclass> <bodycontent>JSP</bodycontent> <attribute> <name>json</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>prjNature</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>bookName</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>tempDir</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>prjCode</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag>
6. action
/**
* 處理PDF導(dǎo)出
*
*/
@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<String, String> baseInfo = new HashMap<String, String>();
baseInfo.put("tempDir", tempDir);
// 項(xiàng)目編號(hào)
baseInfo.put("prjCode", prjCode);
// 項(xiàng)目類型
String prjNature = project.getPrjNature();
baseInfo.put("prjNature", prjNature);
// 水印名稱格式:watermark+"-"+prjNature
baseInfo.put("waterMarkImg", waterMarkImgDir + File.separator + "watermark-" + prjNature + ".png");
// 負(fù)責(zé)人
Person person = personService.getPerson(project.getPsnCode());
String zhName = person.getZhName();
baseInfo.put("zhName", addStr(9, "<br/>", zhName));
// 項(xiàng)目編號(hào)
String prjNo = project.getPrjNo();
baseInfo.put("prjNo", prjNo);
// 項(xiàng)目來(lái)源
ConstDictionary cd = constDictionaryService.findCdByCategoryCode("project_from", project.getGrantNo());
String project_from = cd.getzh_cn_caption();
baseInfo.put("project_from", addStr(9, "<br/>", 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;
baseInfo.put("startEndDate", startEndDate);
// 項(xiàng)目類別--資助類別
String grantName = project.getGrantName();
baseInfo.put("grantName", addStr(9, "<br/>", grantName));
// 合同金額
String totalAmt = project.getTotalAmt().toString();
BigDecimal totalAmt_ = checkNumber(totalAmt);
baseInfo.put("totalAmt", totalAmt_.toString());
// 項(xiàng)目名稱
String zhTitle = project.getZhTitle();
baseInfo.put("zhTitle", addStr(38, "<br/>", zhTitle));
List<Map<String, String>> ps = null;
try {
ps = getMembers(project.getPrjXml());
} catch (Exception e) {
e.printStackTrace();
}
String bookName = "";
// 判斷項(xiàng)目類型
Map<String, Object> itemMap = new HashMap<String, Object>();
if (prjNature.equalsIgnoreCase("1")) {
bookName = "第一份合同";
// 獲取fdPlanDetail
List<Map<String, Object>> list = fdPlanDetailService.getFdPlanDetailsByPrjCode(Long.parseLong(prjCode));
// test
/*
* Map<String, Object> test = new HashMap<String, Object>(); test.put("itemValue", "6");
* test.put("itemName", "差旅費(fèi)"); test.put("remark", "xxxxx"); list.add(test);
*/
for (Map<String, Object> 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<String, Object> data = new HashMap<String, Object>();
// 添加比例
data.put("proportion", proportion.toString());
// 檢測(cè)金額規(guī)范
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<String, Object> map = new HashMap<String, Object>();
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);
Struts2Utils.getRequest().setAttribute("tempDir", tempDir);
Struts2Utils.getRequest().setAttribute("prjCode", prjCode);
return "exprotPdf2";
}
public List<Map<String, String>> getMembers(String xmlData) throws Exception {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
Document doc = DocumentHelper.parseText(xmlData);
Node ps = doc.selectSingleNode("/data/project/persons");
List<Node> psList = ps.selectNodes("person");
String totalAmt = doc.selectSingleNode("/data/project/basic_info/total_amt").getText();
for (Node person : psList) {
Map<String, String> map = new HashMap<String, String>();
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, "<br/>", 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, "<br/>", 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, "<br/>", 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();
}
/**
* 兩個(gè)數(shù)字/英文
*
* @param str
* @param num
* @return 最終索引
*/
public static int getEndIndex(String str, double num) {
int idx = 0;
int count = 0;
double val = 0.00;
// 判斷是否是英文/數(shù)字
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橫向科研項(xiàng)目立項(xiàng)通知書(shū)";
} else if (project.getPrjNature().equalsIgnoreCase("2")) {
// 縱向
wartermark = "CTGU縱向科研項(xiàng)目立項(xiàng)通知書(shū)";
}
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位小數(shù)
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);// 在內(nè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文件(模板文件)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>打印預(yù)覽</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> ...... </head> <body> </body> </html>
預(yù)覽效果:

打印效果:

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
JVM入門(mén)之類加載與字節(jié)碼技術(shù)(類加載與類的加載器)
Java字節(jié)碼增強(qiáng)指的是在Java字節(jié)碼生成之后,對(duì)其進(jìn)行修改,增強(qiáng)其功能,這種方式相當(dāng)于對(duì)應(yīng)用程序的二進(jìn)制文件進(jìn)行修改。Java字節(jié)碼增強(qiáng)主要是為了減少冗余代碼,提高性能等2021-06-06
java實(shí)現(xiàn)查找PDF關(guān)鍵字所在頁(yè)碼及其坐標(biāo)
這篇文章主要介紹了java實(shí)現(xiàn)查找PDF關(guān)鍵字所在頁(yè)碼及其坐標(biāo)的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09
自定義Spring Security的身份驗(yàn)證失敗處理方法
在本篇文章里小編給大家整理了一篇關(guān)于自定義Spring Security的身份驗(yàn)證失敗的處理方法,有需要的朋友們學(xué)習(xí)下。2019-05-05

