最近写个指定打印机打印条码,并且上传服务器保存备份,方便下次打印
如果不需要上传直接将图片流直接给 new FileInputStream(filePath); Doc doc = new SimpleDoc(图片流, dof, das);
思路:
1、在前台用div画布局
2、转成base64图片数据流
3、将数据流发送给后台
4、后台进行数据解码并且上传
5、上传成功后根据路径和打印机名称调动打印机打印
PS:可能写的不是很详细大家凑合看
1、在前台用div画布局
HTML
<#include "../include/header.html" />
<script type="text/javascript">
var viewModel = Hap.createGridViewModel('#grid');
viewModel.model = {};
</script>
<body>
<div id="page-content">
<div class="pull-left" id="toolbar-btn" style="padding-bottom:10px;">
<span class="btn btn-primary k-grid-add" style="float:left;margin-right:5px;" onclick="MyPrint(viewModel.model)" >打印</span>
</div><br/>
</div>
<!--条码-->
<div id="barCode"></div>
<!--一维码js-->
<script src="${base.contextPath}/lib/prints/jquery-barcode.js"></script>
<!--二维码js-->
<script src="${base.contextPath}/lib/prints/jquery-qrcode.min.js"></script>
<!--生成图片js-->
<script src="${base.contextPath}/lib/html2canvas/html2canvas.js"></script>
<script src="${base.contextPath}/lib/html2canvas/bluebird.min.js"></script>
<script src="${base.contextPath}/lib/html2canvas/downLoadImg.js"></script>
<!--
一维码和二维码自行下载
html2canvas.js,bluebird.min.js,downLoadImg.js
这三个文件在 https://download.csdn.net/download/qq_37511501/10232976
-->
<script src="${base.contextPath}/lib/prints/print.js"></script>
</body>
</html>
print.
JS
2、转成base64图片数据流
3、将数据流发送给后台
/*
* Create By: lkj
* Create Date: 2018年08月27日10:10:37
* Desc: 打印工具
*
* */
function MyPrint(printData) {
/**
*
* 描述: 该方法判断进入哪一个打印方法
* @auther: lkj
* @date: 2018/8/28 上午9:21
*
*/
// 根据类型判断进入那个方法
printData.type = "TEST2";
printData.text = "000002RSEOT";
printData.code = "21442650";
printData.printName = "HP DeskJet 2600 series";
if(printData.type == "TEST"){//打印一维码 内部追溯条码
InternalTracingBarCode(printData);
}else if(printData.type == "TEST2"){// ZS11E电池包客户追溯条码
K288ABatteryPackCustomerTraceabilityBarCode(printData);
}
}
function K288ABatteryPackCustomerTraceabilityBarCode(printData) {
/**
*
* 描述:
* @auther: lkj
* @date: 2018/8/28 上午9:33
* @param:printData 需要打印的数据
*/
// 先进行判断该条码是否已经打印过,如果打印过则直接打印 如果没有打印则获取服务器照片存储路径
var fileName = printData.text+"-2.png";
var isPrint = myPostAjax("/is/print",{fileName:fileName,printName:printData.printName});
if(isPrint.success){
alert("打印成功");
return;
}else{
if(isPrint.message != null && isPrint.message != "" && isPrint.message != undefined){
alert(isPrint.message);
return;
}
}
var barCode = '<div id="TEST">';
barCode += '<div id="towCode" style="float: left;margin:20px 10px 20px 5px;"></div>';
barCode += '<div id="content" style="float: left;margin:20px 10px 20px 5px;">';
barCode += '<span><font size="6px">1234</font><font size="8px">2234</font></span><br/>';
barCode += '<span><font size="6px">1234567822345678</font></span><br/>';
barCode += '<span><font size="6px">12345678</font></span><br/>';
barCode += '<span><font size="6px">1234567822345678</font></span>';
barCode += '</div>';
barCode += '<div id="towCode2" style="float: left;margin:20px 10px 20px 5px;"></div>';
barCode += '</div>';
var width = 200;// 二维码宽高
var height = 200;
$("#barCode").html(barCode); // 设置条码内容
$("#TEST").show(); // 显示
// 宽高必须设置,否则无法上传
$("#TEST").attr("style","width:"+870+"px;height:245px");
$('#towCode').qrcode({
render: "canvas",
text: printData.text,
width: width,
height: height,
});
$('#towCode2').qrcode({
render: "canvas",
text: printData.text,
width: width,
height: height,
});
// 设置名称 一维码或二维码内容 加类型 一维码为-1 二维码为-2
getImgStr("TEST",fileName,isPrint.code,printData.printName);
}
function InternalTracingBarCode(printData) {
/**
*
* 描述: 打印一维码 内部追溯条码
* @auther: lkj
* @date: 2018/8/28 上午9:21
* @param:printData 需要打印的数据
*
*/
// 先进行判断该条码是否已经打印过,如果打印过则直接打印 如果没有打印则获取服务器照片存储路径
var fileName = printData.text+"-1.png";
var isPrint = myPostAjax("/is/print",{fileName:fileName,printName:printData.printName});
if(isPrint.success){
alert("打印成功");
return;
}else{
if(isPrint.message != null && isPrint.message != "" && isPrint.message != undefined){
alert(isPrint.message);
return;
}
}
// 设置条码布局 PS可以先在工具上画好再复制过来
// 改字体样式和条码样式一样,可以自定义更改
var fontStyle = "clear:both; background-color: #FFFFFF; color: #000000; text-align: center; font-size: 20px; margin-top: 5px;text-align: center;";
var barCode = '<div id="TEST">';
barCode += '<br/><div id="bcTarget"></div>';
barCode += '<div id="code"></div>';
barCode += '</div>';
$("#barCode").html(barCode);// 设置条码内容
$("#TEST").show();// 显示
$("#bcTarget").barcode(printData.text, "code128",{barWidth:4,barHeight:160,fontSize:20});
fontStyle += "width:"+$("#bcTarget").width()+"px;";
$("#TEST").attr("style","width:"+$("#bcTarget").width()+"px;");
$("#code").attr("style",fontStyle);// K288A电池包客户追溯条码
$("#code").html(printData.code);// 设置显示条码
// 设置名称 一维码或二维码内容 加类型 一维码为-1 二维码为-2
getImgStr("TEST",fileName,isPrint.code,printData.printName);
}
function getImgStr(id,fileName,filePath,printName) {
/**
*
* 描述: 将div根据id转图片流
* @auther: lkj
* @date: 2018/8/28 上午9:20
* @param:id:DIV的id
* @param:codeContent:条码名称
* @param:filePath:服务器存储路径
*
*/
html2canvas($("#"+id), {
onrendered: function(canvas) {
canvas.id = "mycanvas";
// 将div转成图片的字符流
var img = convertCanvasToImage(canvas);
// 设置需要传参参数 图片数据流 文件名称 文件存储路径
var obj = {imgStr:img.src,fileName:fileName,filePath:filePath,printName:printName};
// 发送请求至后台
var printResult = myPostAjax("/print/internal/tracing/bar/code",obj);
if(printResult.success){
alert("打印成功");
}else{
alert(printResult.message);
}
$("#"+id).hide();// 隐藏
},
background:'white'// 背景白色
});
}
function myPostAjax(url,data){
/**
*
* 描述: 封装ajax
* @auther: lkj
* @date: 2018/8/28 上午9:21
*
*/
var resultData = new Object();
$.ajax({
type:"POST",
url:_basePath+url,
data:data,
dataType:'json',
contentType:'application/x-www-form-urlencoded',
async:false,
success:function (result) {
resultData = result;
}
})
return resultData;
}
JAVA
4、后台进行数据解码并且上传
5、上传成功后根据路径和打印机名称调动打印机打印
Controller
package com.hand.utils.prints.controllers;
import com.hand.hap.core.IRequest;
import com.hand.hap.system.controllers.BaseController;
import com.hand.hap.system.dto.ResponseData;
import com.hand.utils.components.mapper.UtilMapper;
import com.hand.utils.prints.dto.PrintDto;
import com.hand.utils.prints.service.IPrintService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
/**
* @Auther:lkj
* @Date:2018/8/27 13:44
* @E-mail:
* @Description:条码打印工具
*/
@Controller
public class PrintController extends BaseController {
@Autowired
private IPrintService service;
@Autowired
private UtilMapper utilMapper;
@RequestMapping(value = "/print/internal/tracing/bar/code")
@ResponseBody
public ResponseData scanningKeyPartsBarcode(PrintDto data, HttpServletRequest request){
/**
*
* 功能描述: 打印内部追溯条码 并且上传至服务器备份
*
* @auther:lkj
* @date:2018/8/27 下午1:47
* @param:[data, request]
* @return:com.hand.hap.system.dto.ResponseData
*
*/
IRequest requestCtx = createRequestContext(request);
ResponseData responseData = new ResponseData();
try {
responseData = service.printInternalTracingBarCode(requestCtx,data);
} catch (Exception e) {
e.printStackTrace();
responseData.setSuccess(false);
responseData.setMessage(e.getMessage());
String insertMysql = "INSERT INTO hme_print_event(ERROR_MSG,FILE_PATH,PRINT_NAME)VALUES";
insertMysql += "('"+e.getMessage()+"','"+data.getFilePath()+"/"+data.getFileName()+"','"+data.getPrintName()+"')";
utilMapper.insertMysql(insertMysql);
}
return responseData;
}
@RequestMapping(value = "/is/print")
@ResponseBody
public ResponseData isPrint(PrintDto data, HttpServletRequest request){
/**
*
* 功能描述: 查询改条码是否打印过 如果打印过则直接打印 不在上传
*
* @auther:lkj
* @date:2018/8/27 下午1:47
* @param:[data, request]
* @return:com.hand.hap.system.dto.ResponseData
*
*/
IRequest requestCtx = createRequestContext(request);
ResponseData responseData = new ResponseData();
try {
responseData = service.isPrint(requestCtx,data);
} catch (Exception e) {
e.printStackTrace();
responseData.setSuccess(false);
responseData.setMessage(e.getMessage());
String insertMysql = "INSERT INTO hme_print_event(ERROR_MSG,FILE_PATH,PRINT_NAME)VALUES";
insertMysql += "('"+e.getLocalizedMessage()+"','"+data.getFilePath()+"/"+data.getFileName()+"','"+data.getPrintName()+"')";
utilMapper.insertMysql(insertMysql);
}
return responseData;
}
}
IPrintService
package com.hand.utils.prints.service;
import com.hand.hap.core.IRequest;
import com.hand.hap.system.dto.ResponseData;
import com.hand.utils.prints.dto.PrintDto;
import com.hand.workshops.dto.WorkshopsIpc;
public interface IPrintService {
/**
*
* 功能描述: 打印内部追溯条码 并且上传至服务器备份
*
* @auther:lkj
* @date:2018/8/27 下午1:48
* @param requestCtx 用户信息
* @param data 数据
* @return:ResponseData
*/
ResponseData printInternalTracingBarCode(IRequest requestCtx, PrintDto data) throws Exception;
/**
*
* 功能描述:查询改条码是否打印过 如果打印过则直接打印 不在上传
*
* @auther:lkj
* @date:2018/8/27 下午2:19
* @param requestCtx 用户信息
* @param data 数据
* @return:ResponseData
*
*/
ResponseData isPrint(IRequest requestCtx, PrintDto data) throws Exception;
}
PrintServiceImpl
package com.hand.utils.prints.service.impl;
import com.hand.hap.core.IRequest;
import com.hand.hap.system.dto.ResponseData;
import com.hand.utils.components.mapper.UtilMapper;
import com.hand.utils.prints.dto.PrintDto;
import com.hand.utils.prints.service.IPrintService;
import com.hand.utils.uploads.service.impl.UploadServiceImpl;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.print.*;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PrintQuality;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
@Service
@Transactional(rollbackFor = Exception.class)
public class PrintServiceImpl implements IPrintService{
private static final Logger logger = LoggerFactory.getLogger(PrintServiceImpl.class);
@Autowired
private UtilMapper utilMapper;
// 因为这边是工厂的业务,所以我这边需要把错误信息记录到数据库下,好方便以后查看错误信息
private String insertErrorMsgSql = "INSERT INTO hme_print_event(ERROR_MSG,FILE_PATH,PRINT_NAME)VALUES";
@Override
public ResponseData printInternalTracingBarCode(IRequest requestCtx, PrintDto data)throws Exception {
/**
*
* 功能描述: 打印内部追溯条码 并且上传至服务器备份
*
* @auther:lkj
* @date:2018/8/27 下午1:50
* @param:[requestCtx, data]
* @return:com.hand.hap.system.dto.ResponseData
*
*/
ResponseData responseData = new ResponseData();
String filename = data.getFileName();
if(!ifNotNull(data.getImgListStr())){
responseData.setSuccess(false);
responseData.setMessage("图片不可以为空");
String insertMysql = insertErrorMsgSql+"('图片不可以为空','"+filename+"','"+data.getPrintName()+"')";
utilMapper.insertMysql(insertMysql);
return responseData;
}
if(!ifNotNull(data.getFileName())){
responseData.setSuccess(false);
responseData.setMessage("图片名称不可以为空");
String insertMysql = insertErrorMsgSql+"('图片名称不可以为空','"+filename+"','"+data.getPrintName()+"')";
utilMapper.insertMysql(insertMysql);
return responseData;
}
String imgStr = data.getImgStr().split(",")[1];
UploadServiceImpl.GenerateImage(imgStr,data.getFilePath()+"/"+filename);
/* UploadServiceImpl.GenerateImage 之前写的上传图片工具
//解码
public static boolean GenerateImage(String imgStr, String imgFilePath) throws IOException {
// 对字节数组字符串进行Base64解码并生成图片
if (imgStr == null) // 图像数据为空
return false;
BASE64Decoder decoder = new BASE64Decoder();
// Base64解码
byte[] bytes = decoder.decodeBuffer(imgStr);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
// 生成jpeg图片
OutputStream out = new FileOutputStream(imgFilePath);
out.write(bytes);
out.flush();
out.close();
return true;
}*/
// 上传条码后打印条码
String filePath = data.getFilePath()+"/"+filename;
return print(filePath,data.getPrintName());
}
@Override
public ResponseData isPrint(IRequest requestCtx, PrintDto data) throws Exception {
/**
*
* 功能描述: 查询改条码是否打印过 如果打印过则直接打印 不在上传
*
* @auther:lkj
* @date:2018/8/27 下午2:32
* @param:[requestCtx, data]
* @return:com.hand.hap.system.dto.ResponseData
*
*/
ResponseData responseData = new ResponseData();
String sql = "SELECT T.PROFILE_VALUE FROM SYS_PROFILE_VALUE T WHERE ";
sql += "T.PROFILE_ID = ( SELECT PROFILE_ID FROM sys_profile WHERE PROFILE_NAME = 'UPLOAD_BARCODE' ) ";
String filePath = utilMapper.mysql(sql);
if(!ifNotNull(filePath)){
responseData.setSuccess(false);
responseData.setMessage("UPLOAD_BARCODE:快码没有维护条码存放地址");
String insertMysql = insertErrorMsgSql+"('UPLOAD_BARCODE:快码没有维护条码存放地址','','')";
utilMapper.insertMysql(insertMysql);
return responseData;
}
File file;
// 先判断该文件夹是否存在 如果不存在则创建文件夹,并且返回路径
file = new File(filePath);
if(!file.exists()){
file.mkdirs();
responseData.setSuccess(false);
responseData.setCode(filePath);
return responseData;
}else{//如果存在则查询改条码是否打印过,如果打印过就直接打印,否则返回路径
String fileName = filePath+"/"+data.getFileName();
file = new File(fileName);
if(file.exists()){
return print(fileName,data.getPrintName());
}
responseData.setSuccess(false);
responseData.setCode(filePath);
return responseData;
}
}
public ResponseData print(String filePath,String printName)throws Exception {
/**
*
* 功能描述:调用指定打印机打印图片
*
* @auther:lkj
* @date:2018/8/28 下午1:37
* @param:[filePath]
* @return:void
*
*/
ResponseData responseData = new ResponseData();
FileInputStream fin = null;
javax.print.PrintService[] printServices = PrinterJob.lookupPrintServices();
if(printServices.length == 0){
String insertMysql = insertErrorMsgSql+"('打印机列表为空','"+filePath+"','"+printName+"')";
utilMapper.insertMysql(insertMysql);
responseData.setSuccess(false);
responseData.setMessage("打印机列表为空");
return responseData;
}
javax.print.PrintService printService = null;
for (int i = 0; i < printServices.length; i++) {
String sps = printServices[i].toString();
logger.info("Print :" + sps);
System.out.println("Print :" + sps);
// 查询匹配打印机
if (sps.contains(printName)) {
printService = printServices[i];
break;
}
}
if (null == printService) {
String insertMysql = insertErrorMsgSql+"('没有匹配到所指定的打印机','"+filePath+"','"+printName+"')";
utilMapper.insertMysql(insertMysql);
responseData.setSuccess(false);
responseData.setMessage("没有匹配到所指定的打印机");
return responseData;
}
System.out.println("Print Start");
logger.info("Print Start");
DocFlavor dof = null;
if (filePath.endsWith(".gif")) {
dof = DocFlavor.INPUT_STREAM.GIF;
} else if (filePath.endsWith(".jpg")) {
dof = DocFlavor.INPUT_STREAM.JPEG;
} else if (filePath.endsWith(".png")) {
dof = DocFlavor.INPUT_STREAM.PNG;
}
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
pras.add(OrientationRequested.PORTRAIT);
pras.add(new Copies(1));
pras.add(PrintQuality.HIGH);
DocAttributeSet das = new HashDocAttributeSet();
// 设置打印纸张的大小(以毫米为单位)
das.add(new MediaPrintableArea(0, 0, 210, 296, MediaPrintableArea.MM));
fin = new FileInputStream(filePath);
Doc doc = new SimpleDoc(fin, dof, das);
DocPrintJob job = printService.createPrintJob();
job.print(doc, pras);
fin.close();
logger.info("打印成功!文件:"+filePath+"数量为:"+1);
System.out.println("Print End");
logger.info("Print End");
return responseData;
}
// 判断是否为空
private boolean ifNotNull(Object o) {
if (o == null || "".equals(o)) {
return false;
}
return true;
}
}
DTO
package com.hand.utils.prints.dto;
/**
* @Auther:lkj
* @Date:2018/8/27 13:44
* @E-mail:
* @Description:
*/
public class PrintDto {
private String imgStr;// 图片流
private String[] imgListStr;// 批量上传
private String fileName;//文件名称
private String filePath;// 文件路径
private String printName;// 打印机名称
public String getPrintName() {
return printName;
}
public void setPrintName(String printName) {
this.printName = printName;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getImgStr() {
return imgStr;
}
public void setImgStr(String imgStr) {
this.imgStr = imgStr;
}
public String[] getImgListStr() {
imgListStr = this.getImgStr().split(",");
return imgListStr;
}
public void setImgListStr(String[] imgListStr) {
this.imgListStr = imgListStr;
}
}