佳博蓝牙打印机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.cn
