前段时间,因项目需求,需要将数据图片打印成PDF下载保存,
项目采用前后端分离模式,前端采用angular,后端springboot,
流程:1.前端返回JSON对象,2.后端接收JSON对象,将之转化成json字符串,并解析成 list 对象,3.创建Document对象,4.创建IMGE对象,5.创建PdfTable对象 6. 创建Paragraph文字对象 7. 将IMGE/PdfTable/Paragraph对象按照业务需求顺序添加到Document对象中
代码如下:
引入如下jar包:
代码:
@RequestMapping(value = "printData")
@ResponseBody
public void printData(HttpServletRequest request, @RequestBody JSONObject obj, HttpServletResponse resp) throws NoSuchFieldException {
String path2 = request.getServletContext().getRealPath("/");
String a = obj.toJSONString();
String aa = a.substring(a.indexOf("["),a.indexOf("]")+1);
List<IdeaPrintVo> list = JSON.parseArray(aa, IdeaPrintVo.class);
String imgpathhh = list.get(0).getImgpath();
logger.info("---------------图片路径:"+imgpathhh+"-------------------");
imgpathhh = imgpathhh.replaceAll("\\\\","/");
//String imgpathhh = "http://47.94.234.23:8080/attachment/epc/Pictures/13S0K01/IMGE/ATM0100.PNG";
//列名
String headerStr = "Refnr Part Number PartsDescriptionUnit Qty Ordered Qty";
BaseFont bf;
Font font = null;
Document document = new Document(PageSize.A4, 20, 20, 30, 30);
//referenceNo 参照编号
//partNo 零部件号码
//cHNName 零部件中文名称
//qty 数量
//stockQty 最后一列 值需要动态判
//检查第五列的值,并赋值
for (IdeaPrintVo vo:list ) {
if ("false".equals(vo.getCheckFlag())){
//if 零部件未选中时:
vo.setStockQty(0);
}else{
String qty = vo.getQty();
if ("N".equals(qty)){
//UnitQty的值为N,Ordered Qty的值为1
vo.setStockQty(1);
}else if (qty.contains("(")){
//如果UnitQty的值带括号,Ordered Qty的值为括号内部的值
vo.setStockQty(Integer.parseInt(qty.substring(1,qty.length()-1)));
}else {
vo.setStockQty(Integer.parseInt(qty));
}
}
}
try {
bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false, false, null, null);//创建字体
font = new Font(bf, 12);//使用字体
// http://47.94.234.23:8080/attachment/epc/Pictures/13S0K01/IMGE/ATM0100.PNG
Image img = Image.getInstance(imgpathhh);
logger.info("---------------获取图片对象成功!-------------------");
float documentWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();
float documentHeight = documentWidth / 580 * 320;//重新设置宽高
img.scaleAbsolute(documentWidth, documentHeight);//重新设置宽高
img.setBorder(1);
img.setBorderWidth(1);
img.setBorderWidthLeft(1);
img.setBorderWidthRight(1);
img.setBorderWidthBottom(1);
//创建table表
float[] columnWidths = {0.125f,0.2f,0.425f,0.125f,0.125f};
PdfPTable table = new PdfPTable(5);
table.setWidths(columnWidths);
table.setHorizontalAlignment(Element.ALIGN_CENTER); //垂直居中
table.setWidthPercentage(100);//表格的宽度为100%
table.setSpacingBefore(20);
table.getDefaultCell().setBorderWidth(0);//不显示边框
for (int j=0;j<list.size();j++) {
//获取所有的属性
String[] strs = getAllFileds(list.get(j));
for (int i = 0;i<5;i++){
String strss = "";
Object value = getFieldValueByName(strs[i],list.get(j));
if (null!=value){
strss = value.toString();
}
PdfPCell cell = new PdfPCell(new Paragraph(strss,font));
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setFixedHeight(30);
cell.setBorder(0);
if (j==0){
cell.setBorderWidthTop(1);
}
if (i==1){
cell.setLeft(10);
}
table.addCell(cell);
}
}
String imgtext = "Block "+list.get(0).getBlockNo()+" THROTTLE BODY";
Paragraph imgP = new Paragraph(imgtext,font);
Paragraph paragraphT = new Paragraph(headerStr,font);
paragraphT.setSpacingBefore(30);
PdfWriter.getInstance(document, new FileOutputStream(path2+list.get(0).getBlockNo()+".pdf"));
document.open();
document.add(img);
document.add(imgP);
document.add(paragraphT);
document.add(table);
document.close();
//处理文件,流
String path = path2+list.get(0).getBlockNo()+".pdf";
FileInputStream proxyIn = new FileInputStream(new File(path));
resp.reset();
resp.setContentType("application/pdf");
resp.setCharacterEncoding("UTF-8");
//设置文件的名字
String filename = list.get(0).getBlockNo()+".pdf";
resp.addHeader("Content-Disposition", "attachment; filename="+filename);
// 用response对象获取输出流
OutputStream os = resp.getOutputStream();
byte[] bos = new byte[proxyIn.available()];
proxyIn.read(bos);
os.write(bos);
os.flush();
os.close();
//删除文件
File fileDelete = new File(path);
if (fileDelete.exists()&&fileDelete.isFile()){
fileDelete.delete();
}
} catch (Exception e) {
System.out.println("file create exception");
}
}
/**
* 获取所有属性
* @param vo
* @return String []
*/
private String [] getAllFileds(IdeaPrintVo vo) {
Field[] ss = vo.getClass().getDeclaredFields();
String[] strs = new String[5];
for (int i=0;i<ss.length;i++){
String name = ss[i].getName();//属性名字
if ("referenceNo".equals(name)){
strs[0]=name;
}
if ("partNo".equals(name)){
strs[1]=name;
}
if ("cHNName".equals(name)){
strs[2]=name;
}
if ("qty".equals(name)){
strs[3]=name;
}
if ("stockQty".equals(name)){
strs[4]=name;
}
}
return strs;
}
/**
* 根据属性名获取属性值
* */
private Object getFieldValueByName(String fieldName, Object o) {
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getter = "get" + firstLetter + fieldName.substring(1);
Method method = o.getClass().getMethod(getter, new Class[] {});
Object value = method.invoke(o, new Object[] {});
return value;
} catch (Exception e) {
return null;
}
}
前端代码如下:
printData(data: any) {
return this.httpClient
.post(
`${this.requesthead}/ideaParts/printData`,
JSON.stringify(data),
{
headers: new HttpHeaders().set(
"Content-Type",
"application/json; charset=UTF-8"
),
responseType: 'blob',
observe: 'response'
}
)
.subscribe((res: HttpResponse<Blob>) => {
const path = res.headers.get('content-disposition');
const fileName = path.substr(path.indexOf('=') + 1);
saveAs(res.body, decodeURI(fileName));
});
}
效果如下: