From adbe071c0551defaef1d8247db4f587aafb69eeb Mon Sep 17 00:00:00 2001 From: "DESKTOP-J7ED0MB\\yinjinlu" <411641505@qq.com> Date: Mon, 17 Oct 2022 22:00:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9D=A1=E7=A0=81=E6=94=AF=E6=8C=81=E4=BA=8C?= =?UTF-8?q?=E7=BB=B4=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ktg-common/pom.xml | 6 + .../ktg/common/constant/UserConstants.java | 8 + .../ktg/common/utils/barcode/BarcodeUtil.java | 213 +++++++++++++++--- .../wm/service/impl/WmBarcodeServiceImpl.java | 8 +- 4 files changed, 202 insertions(+), 33 deletions(-) diff --git a/ktg-common/pom.xml b/ktg-common/pom.xml index 321f9d0..cb248e6 100644 --- a/ktg-common/pom.xml +++ b/ktg-common/pom.xml @@ -144,6 +144,12 @@ 2.0 + + com.google.zxing + core + 3.3.3 + + \ No newline at end of file diff --git a/ktg-common/src/main/java/com/ktg/common/constant/UserConstants.java b/ktg-common/src/main/java/com/ktg/common/constant/UserConstants.java index d1d94f5..56211d6 100644 --- a/ktg-common/src/main/java/com/ktg/common/constant/UserConstants.java +++ b/ktg-common/src/main/java/com/ktg/common/constant/UserConstants.java @@ -184,4 +184,12 @@ public class UserConstants public static final String VIRTUAL_WS ="XBKKQ_VIRTUAL"; public static final String VIRTUAL_WA ="XBKKW_VIRTUAL"; + /** + * 条码类型 + */ + public static final String QR_CODE = "QR_CODE"; + public static final String EAN_CODE = "EAN_CODE"; + public static final String UPC_CODE = "UPC_CODE"; + public static final String CODE39_CODE = "CODE39_CODE"; + } diff --git a/ktg-common/src/main/java/com/ktg/common/utils/barcode/BarcodeUtil.java b/ktg-common/src/main/java/com/ktg/common/utils/barcode/BarcodeUtil.java index 4ff582a..16e11a4 100644 --- a/ktg-common/src/main/java/com/ktg/common/utils/barcode/BarcodeUtil.java +++ b/ktg-common/src/main/java/com/ktg/common/utils/barcode/BarcodeUtil.java @@ -1,59 +1,102 @@ package com.ktg.common.utils.barcode; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; +import com.ktg.common.constant.UserConstants; import com.ktg.common.utils.StringUtils; +import org.krysalis.barcode4j.impl.AbstractBarcodeBean; import org.krysalis.barcode4j.impl.code39.Code39Bean; +import org.krysalis.barcode4j.impl.upcean.EAN13Bean; +import org.krysalis.barcode4j.impl.upcean.UPCABean; import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider; import org.krysalis.barcode4j.tools.UnitConv; -import java.io.ByteArrayOutputStream; +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; -import java.io.FileNotFoundException; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; -import java.io.File; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; public class BarcodeUtil { - - public static File generateFile(String msg, String path) { + private static final String CHARSET = "utf-8"; + private static final String FORMAT_NAME = "PNG"; + // 二维码尺寸,长宽尺寸一致 + private static final int QRCODE_SIZE = 300; + // 二维码内部logo的宽和高 + private static final int WIDTH = 60; + private static final int HEIGHT = 60; + + public static File generateBarCode(String msg, String barCodeFormat, String path) { File file = new File(path); try { - generate(msg, new FileOutputStream(file)); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } + if(StringUtils.isEmpty(msg)){ + throw new RuntimeException("条码内容不能为空!"); + } + //检查父级目录是否存在,不存在先新建 + File parentFile = file.getParentFile(); + if(!parentFile.exists()){ + parentFile.mkdirs(); + } + /* + * 生成条码 + */ + if(UserConstants.QR_CODE.equals(barCodeFormat)){ + //生成二维码 + generateQRCode(msg, null, file.getAbsolutePath(), false); + }else{ + //生成一维码 + generateLineCode(msg, barCodeFormat, file.getAbsolutePath()); + } + }catch (Exception e) { + throw new RuntimeException("生成条码发生错误:"+e.getMessage()); + } return file; } - - public static byte[] generate(String msg) { - ByteArrayOutputStream ous = new ByteArrayOutputStream(); - generate(msg, ous); - return ous.toByteArray(); - } - - - public static void generate(String msg, OutputStream ous) { - if (StringUtils.isEmpty(msg) || ous == null) { - return; - } - - Code39Bean bean = new Code39Bean(); - + /** + * 生成一维条形码 + * @param msg 条形码的内容 + * @param barCodeFormat 条形码格式 see {@link UserConstants} + * @param destFilePath 条形码存储的路径 + * @throws Exception + */ + public static void generateLineCode(String msg,String barCodeFormat,String destFilePath) throws Exception { + AbstractBarcodeBean bean = null; + if(UserConstants.EAN_CODE.equals(barCodeFormat)){ + bean = new EAN13Bean(); + }else if(UserConstants.CODE39_CODE.equals(barCodeFormat)){ + bean = new Code39Bean(); + }else if(UserConstants.UPC_CODE.equals(barCodeFormat)){ + bean = new UPCABean(); + }else{ + throw new Exception("不支持的条码类型!"); + } // 精细度 final int dpi = 150; - // module宽度 - final double moduleWidth = UnitConv.in2mm(1.0f / dpi); + if (bean instanceof Code39Bean) { + Code39Bean codeBean = (Code39Bean) bean; + // module宽度 + final double moduleWidth = UnitConv.in2mm(1.0f / dpi); - // 配置对象 - bean.setModuleWidth(moduleWidth); - bean.setWideFactor(3); - bean.doQuietZone(false); + // 配置对象 + bean.setModuleWidth(moduleWidth); + codeBean.setWideFactor(3); + bean.doQuietZone(false); + } String format = "image/png"; try { // 输出到流 - BitmapCanvasProvider canvas = new BitmapCanvasProvider(ous, format, dpi, + BitmapCanvasProvider canvas = new BitmapCanvasProvider(new FileOutputStream(destFilePath), format, dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0); // 生成条形码 @@ -65,4 +108,110 @@ public class BarcodeUtil { throw new RuntimeException(e); } } + /** + * 生成带logo二维码,并保存到磁盘 + * + * @param content 二维码的内容 + * @param imgPath 二维码内部插入的图片路径,如果不需要可以传空 + * @param destFilePath 整个二维码存储的路径 + * @param needCompress 二维码内部插入的图片是否需要压缩的标识 + * @throws Exception 异常 + */ + public static void generateQRCode(String content, String imgPath, String destFilePath, boolean needCompress) throws Exception { + BufferedImage image = createQrCode(content, imgPath, needCompress); + ImageIO.write(image, FORMAT_NAME, new File(destFilePath)); + } + + /** + * 生成二维码图片 + * + * @param content 二维码内容 + * @param imagePath 二维码内部图片路径,如果不需要可以传空 + * @param needCompress 二维码内部图片是否需要压缩标识 + * @return 二维码图片 + * @throws WriterException 异常 + */ + private static BufferedImage createQrCode(String content,String imagePath,boolean needCompress) throws WriterException, IOException { + /** + * EncodeHintType 编码提示类型 枚举类型: + * CHARACTER_SET: 设置字符编码类型 "UTF-8" QR_CODE类型默认的编码格式 "ISO-8859-1" + * MARGIN: 设置二维码边距,单位像素,值越小,二维码距离四周越近 + * ERROR_CORRECTION: 设置误差校正 + * ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction + * 不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的 + */ + Map hints = new ConcurrentHashMap<>(3); + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); + hints.put(EncodeHintType.CHARACTER_SET, CHARSET); + hints.put(EncodeHintType.MARGIN, 1); + //加密生成二维码的矩阵对象 二维的0 1 然后根据特定的值选择属性 + BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints); + int width = bitMatrix.getWidth(); + int height = bitMatrix.getHeight(); + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + //设置二维码的黑色0xFF000000 和白色0xFFFFFFFF + image.setRGB(i, j, bitMatrix.get(i, j) ? 0xFF000000 : 0xFFFFFFFF); + } + } + if (StringUtils.isBlank(imagePath)) { + return image; + } + //插入小图标 logo + insertImage(image, imagePath, needCompress); + return image; + } + /** + * 将logo插入二维码中间 + * + * @param source 生成的二位码存储对象 + * @param imagePath 二维码内部图片的路径 + * 一般的业务场景会把插入的小logo放到oss生成url + * @param needCompress 二维码内部图片是否需要压缩 + * @throws IOException 异常 + */ + private static void insertImage(BufferedImage source, String imagePath, boolean needCompress) throws IOException { + File file = new File(imagePath); + if (!file.exists()) { + //可以自定义抛出异常 + throw new RuntimeException("文件路径不存在:" + imagePath); + } + //这里修改ImageIO.read() 内可以接受Url InputStream File ImageInputStream + Image src = ImageIO.read(file); + int width = src.getWidth(null); + int height = src.getHeight(null); + //是否压缩 + if (needCompress) { + if (width > WIDTH) { + width = WIDTH; + } + if (height > HEIGHT) { + height = HEIGHT; + } + Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH); + BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = tag.getGraphics(); + g.drawImage(image, 0, 0, null); + g.dispose(); + src = image; + } + Graphics2D graphics = source.createGraphics(); + int x = (QRCODE_SIZE - width) / 2; + int y = (QRCODE_SIZE - height) / 2; + graphics.drawImage(src,x,y,width,height,null); + Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6); + graphics.setStroke(new BasicStroke(3f)); + graphics.draw(shape); + graphics.dispose(); + } + + + public static void main(String[] args) { + String msg="item12345678"; + String EANmsg="012345678901"; + String UPCmsg="12345678901"; + String path = "D:/test/barcode/"+UUID.randomUUID()+".png"; + generateBarCode(msg, UserConstants.QR_CODE, path); + } } diff --git a/ktg-mes/src/main/java/com/ktg/mes/wm/service/impl/WmBarcodeServiceImpl.java b/ktg-mes/src/main/java/com/ktg/mes/wm/service/impl/WmBarcodeServiceImpl.java index 2120ba4..9841c8e 100644 --- a/ktg-mes/src/main/java/com/ktg/mes/wm/service/impl/WmBarcodeServiceImpl.java +++ b/ktg-mes/src/main/java/com/ktg/mes/wm/service/impl/WmBarcodeServiceImpl.java @@ -116,7 +116,8 @@ public class WmBarcodeServiceImpl implements IWmBarcodeService @Override public String generateBarcode(WmBarcode wmBarcode) { - File buf = BarcodeUtil.generateFile(wmBarcode.getBarcodeContent(),"./tmp/barcode/"+wmBarcode.getBarcodeContent()+".png"); + File buf = BarcodeUtil.generateBarCode(wmBarcode.getBarcodeContent(), wmBarcode.getBarcodeFormart(), + "./tmp/barcode/" + wmBarcode.getBarcodeContent() + ".png"); MultipartFile file = FileUtils.getMultipartFile(buf); String fileName = null; try { @@ -124,6 +125,11 @@ public class WmBarcodeServiceImpl implements IWmBarcodeService } catch (IOException e) { e.printStackTrace(); return null; + }finally{ + //删除掉临时文件 + if(buf!=null && buf.exists()){ + FileUtils.deleteFile(buf.getAbsolutePath()); + } } return fileName; }