佳博蓝牙打印机PDF在线设计模板
业务场景:自定义的模板通过 佳博蓝牙打印机进行打印
1.打印格式通过代码去拼接(麻烦) 2.直接打印pdf(方便,可延伸业务)
最终方案流程:通过html设计打印界面----》html生成pdf文件模板-----》pdf模板填充数据-----》发送给手机端进行打印
通过html设计打印界面(网上找的条码在线设计,进行的二次开发)
二次开发主要代码块
var head = "<?xml version='1.0' encoding='UTF-8' ?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'><html xmlns='http://www.w3.org/1999/xhtml'><head><title>"+(parseInt(pdfwidth)-25)+"|"+(parseInt(pdfheight)-25)+"</title><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/><style type='text/css' rel='stylesheet'>* { margin: 0; padding: 0; }body { font-family: 'Microsoft YaHei UI'; } "; var footer = "</body></html>"; var sourcesvg; var svgtype;//rect一维码(1.bar) use二维码(2.qr) //把一维码元素替换掉 sourcesvg = $("svg").parent().html(); if (sourcesvg != undefined) { if (sourcesvg.indexOf("<rect x") != -1) { svgtype = "bar"; } else { svgtype = "qr"; } $("svg").parent().html("<img class='sourcesvg' style='height: 100%;width: 100%' src='${" + svgtype + "codeImg}'>"); } //所有img后面都加${img} $("div[class=hiprint-printPaper-content] img").each(function () { $(this).parent().append("thimg") }); if(svgtype == "bar"){ $(".sourcesvg").parent().append("<div class='hibarcode_displayValue'>${code}</div>"); } var clone = $('div.hiprint-printPaper-content').clone(); clone.find('.hiprint-headerLine').remove(); clone.find('.hiprint-footerLine').remove(); clone.find('.hiprint-paperNumber').remove(); var html = clone.html(); var reg = new RegExp("thimg", "g");//g,表示全部替换。 html = html.replace(reg, "</img>");//直接写里面会失效 reg = new RegExp("<br>", "g");//g,表示全部替换。 html = html.replace(reg, "<br/>");//直接写里面会失效 //添加pdf尺寸 head = head + "@page{ size:" + pdfwidth + "mm " + pdfheight + "mm; }"; head = head + "</style></head><body>"; html = head + html + footer; //console.log(html); //删除所有图片的thimg $("div[class=hiprint-printPaper-content] img").each(function () { var tupian=$(this).parent().html(); tupian=tupian.substring(0,tupian.indexOf("thimg")); $(this).parent().html(tupian); }); $(".sourcesvg").parent().html(sourcesvg); var blob = new Blob([html], {type: "text/plain;charset=utf-8"}); saveAs(blob,Math.uuid()+".html");
下面是JAVA后端代码
<!--打印pdf生成--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.4.2</version> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.0.8</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>net.sf.barcode4j</groupId> <artifactId>barcode4j-light</artifactId> <version>2.0</version> </dependency> <!--pdf生成图片--> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.19</version> </dependency>
html生成pdf文件模板-----》pdf模板填充数据
说明:这里的打印html模板文件是上传到配置界面的 然后在数据库保存这个html地址 ,然后后台代码下载
主要代码块
package com.tengnat.mes.configuration.modular.printer.service; import com.tengnat.assist.exception.BusinessException; import com.tengnat.mes.common.consts.ApplicationConst; import com.tengnat.mes.common.enums.IsDelEnum; import com.tengnat.mes.common.utils.file.FileUtil; import com.tengnat.mes.configuration.core.dao.SqlDao; import com.tengnat.mes.configuration.core.utils.BarcodeUtil; import com.tengnat.mes.configuration.core.utils.FreemarkerTemplate; import com.tengnat.mes.configuration.core.utils.PDFUtils; import com.tengnat.mes.configuration.core.utils.QRCodeUtils; import com.tengnat.mes.configuration.modular.printer.dao.PrintTemplateDao; import com.tengnat.mes.configuration.modular.printer.entity.PrintTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; import org.springframework.util.ResourceUtils; import org.xhtmlrenderer.simple.PDFRenderer; import javax.servlet.http.HttpServletRequest; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created by SkinApe on 2020/5/9. * 打印pdf生成 */ @Service public class PrinterPdfService { private String svgtype; @Autowired private PrintTemplateDao printTemplateDao; @Autowired private SqlDao sqlDao; /** * 生成 * @param code 单据 * @param type 模板类型 * @param request * @return */ public List<Map<String,Object>> creatPdf(String code,String type){ //,HttpServletRequest request 这里很纠结springboot打成的jar的锅!!!!!! //String printPath = request.getSession().getServletContext().getRealPath("/")+ "files/print/";//打印路径 String printPath = System.getProperty("user.dir")+ "/files/print/";//打印路径 String tempathPath = printPath+ "template/";//模板路径 String barCodePath = printPath + "images/";//一维码路径 String qrCodePath = printPath + "images/";//二维码路径 QRCodeUtils.mkdirs(barCodePath); QRCodeUtils.mkdirs(qrCodePath); QRCodeUtils.mkdirs(tempathPath); //根据模板查询对应的执行sql PrintTemplate printTemplate=printTemplateDao.findByPrintIdentifyingAndTemplateTypeAndIsDel(type,"bluetooth" + "", IsDelEnum.DEL_No.getCode()); Map<String,Object> params = new HashMap<>(); Map<String, Object> valueMap = new HashMap<>(); List<Map> dataMaplist = new ArrayList<>(); //执行查询sql if (printTemplate==null) { throw new BusinessException("无打印模板:"+type); } params.put(ApplicationConst.SQL_KEY, printTemplate.getSql()); valueMap.put("code", code); params.put(ApplicationConst.SQL_QUERY_VALUE_KEY, valueMap); dataMaplist = sqlDao.findList(params); List<Map<String,Object>> resultlist=new ArrayList<>(); for (Map<String,Object> dataMap:dataMaplist){ //dataMap.put("code","5201314"); String uuid = UUID.randomUUID().toString(); String pdfPath = printPath + uuid + ".pdf";//pdf String htmlPath = printPath + uuid + ".html";//html try { //下载打印模板 获取打印模板宽度 String pdfwidthHeight=downLoadFromUrl(printTemplate.getTemplateUrl(),uuid+".html",tempathPath); if (svgtype.equals("barcodeImg")){ //生成条形码 File barCodeFile = new File(barCodePath+uuid + "bar.png"); BarcodeUtil.generateToFile(dataMap.get("code").toString(), BarcodeUtil.IMG_TYPE_PNG, barCodeFile); System.out.println("生成条形码完成!"); }else{ //生成二维码 String qRCodePath=QRCodeUtils.encode(dataMap.get("code").toString(),qrCodePath,uuid + "qr.png"); System.out.println("生成二维码完成!"); } //生成html FreemarkerTemplate tp = new FreemarkerTemplate("UTF-8"); tp.setTemplateDirectoryPath(tempathPath); String osName = System.getProperties().getProperty("os.name"); //liunx环境 if(osName.equals("Linux")) { dataMap.put("barcodeImg", barCodePath+uuid + "bar.png"); dataMap.put("qrcodeImg", qrCodePath+uuid + "qr.png"); }else{ dataMap.put("barcodeImg", "/"+barCodePath.replace("\\","/")+uuid + "bar.png"); dataMap.put("qrcodeImg", "/"+qrCodePath.replace("\\","/")+uuid + "qr.png"); } //封装数据 end File htmlFile = new File(htmlPath); tp.processToFile(uuid+".html", dataMap, htmlFile); System.out.println("生成html完成!"); //生成pdf PDFUtils.htmlFileToPDFFile(htmlFile, new File(pdfPath), new File(printPath)); System.out.println("生成pdf完成!"); //生成图片 //PDFUtils.pdfToImage(pdfPath,printPath+uuid + ".png",Integer.parseInt(pdfwidthHeight.split("\\|")[0])*8); //System.out.println("生成pdf图片完成!"); Map<String,Object> result=new HashMap<>(); result.put("pdf","files/print/"+uuid + ".pdf"); result.put("pdfWidth",pdfwidthHeight.split("\\|")[0]); result.put("pdfHeight",pdfwidthHeight.split("\\|")[1]); result.put("code",code); resultlist.add(result); //删除刚刚生成的内容 除了pdf FileUtil.deleteFile(printPath,1,new String[]{uuid}); //throw new BusinessException("删除的路径:"+FileUtil.chu()); } catch (IOException e) { e.printStackTrace(); } catch (Throwable throwable) { throwable.printStackTrace(); } } return resultlist; } /** * 下载打印模板 获取打印模板宽度 和 高度 * @param urlStr * @param fileName * @param savePath * @throws IOException */ public String downLoadFromUrl(String urlStr,String fileName,String savePath) throws IOException{ URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); //设置超时间为3秒 conn.setConnectTimeout(3*1000); //防止屏蔽程序抓取而返回403错误 conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); //得到输入流 InputStream inputStream = conn.getInputStream(); byte[] buffer = new byte[1024]; int len = 0; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while((len = inputStream.read(buffer)) != -1) { bos.write(buffer, 0, len); } bos.close(); //获取自己数组 byte[] getData =bos.toByteArray(); //文件保存位置 File saveDir = new File(savePath); if(!saveDir.exists()){ saveDir.mkdir(); } File file = new File(saveDir+File.separator+fileName); FileOutputStream fos = new FileOutputStream(file); fos.write(getData); String pdfwidthHeight = "0"; String str = new String(getData); if (str.indexOf("barcodeImg")!=-1){ svgtype="barcodeImg"; }else{ svgtype="qrcodeImg"; } //设置匹配规则 String regStr = "<title.*>(.*)</title>"; Pattern pattern = Pattern.compile(regStr); while (str != null) { Matcher m = pattern.matcher(str); if (m.find()) { pdfwidthHeight=m.group(1); break; } } if(fos!=null){ fos.close(); } if(inputStream!=null){ inputStream.close(); } return pdfwidthHeight; } }
佳博蓝牙打印PDFAndroid源码:https://www.baldhome.com/article/40
解压密码!!!!
关注光头e家回复佳博蓝牙打印
本文为程序员之家原创文章,转载无需和我联系,但请注明来自程序员之家www.baldhome.com