使用Java 將前臺傳回的資料,列印成PDF,並插入圖片
阿新 • • 發佈:2018-11-05
前段時間,因專案需求,需要將資料圖片列印成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));
});
}
效果如下: