From 8c6155a0cea4df40a9a6b6c96a845659f8ae0d83 Mon Sep 17 00:00:00 2001
From: Administrator <admin>
Date: Wed, 01 Jun 2022 18:18:24 +0800
Subject: [PATCH] 新增溯源码二维码生成

---
 src/main/java/org/springblade/common/utils/QRCodeUtil.java         |  290 +++++++++++++++++++++++++++++++++++++++++
 pom.xml                                                            |   11 +
 src/main/java/org/springblade/modules/qrcode/QrCodeController.java |  107 +++++++++++++++
 3 files changed, 408 insertions(+), 0 deletions(-)

diff --git a/pom.xml b/pom.xml
index 05a58a3..ea1ec44 100644
--- a/pom.xml
+++ b/pom.xml
@@ -192,6 +192,17 @@
             <artifactId>lombok</artifactId>
             <scope>provided</scope>
         </dependency>
+        <!--  二维码生成  -->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.3.3</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.3.3</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/src/main/java/org/springblade/common/utils/QRCodeUtil.java b/src/main/java/org/springblade/common/utils/QRCodeUtil.java
new file mode 100644
index 0000000..538dd54
--- /dev/null
+++ b/src/main/java/org/springblade/common/utils/QRCodeUtil.java
@@ -0,0 +1,290 @@
+package org.springblade.common.utils;
+
+import com.github.xiaoymin.knife4j.core.util.StrUtil;
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.WriterException;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import com.itextpdf.xmp.impl.Base64;
+import lombok.experimental.UtilityClass;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.imageio.ImageIO;
+import javax.servlet.ServletOutputStream;
+import java.awt.*;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.HashMap;
+
+import static com.google.zxing.client.j2se.MatrixToImageConfig.BLACK;
+import static com.google.zxing.client.j2se.MatrixToImageConfig.WHITE;
+
+/**
+ * <p>QRCodeUtil</p>
+ *
+ * @author lvhaosir6
+ * @version 1.0.0
+ * @date 2020/7/8
+ * @import_date 2021-8-24
+ */
+@Slf4j
+@UtilityClass
+public class QRCodeUtil {
+	/**
+	 * 默认宽度
+	 */
+	private static final Integer WIDTH = 140;
+	/**
+	 * 默认高度
+	 */
+	private static final Integer HEIGHT = 140;
+
+	/**
+	 * LOGO 默认宽度
+	 */
+	private static final Integer LOGO_WIDTH = 22;
+	/**
+	 * LOGO 默认高度
+	 */
+	private static final Integer LOGO_HEIGHT = 22;
+
+	/**
+	 * 图片格式
+	 */
+	private static final String IMAGE_FORMAT = "png";
+	private static final String CHARSET = "utf-8";
+	/**
+	 * 原生转码前面没有 data:image/png;base64 这些字段,返回给前端是无法被解析
+	 */
+	private static final String BASE64_IMAGE = "data:image/png;base64,%s";
+
+	/**
+	 * 生成二维码,使用默认尺寸
+	 *
+	 * @param content 内容
+	 * @return
+	 */
+	public String getBase64QRCode(String content) {
+		return getBase64Image(content, WIDTH, HEIGHT, null, null, null);
+	}
+
+	/**
+	 * 生成二维码,使用默认尺寸二维码,插入默认尺寸logo
+	 *
+	 * @param content 内容
+	 * @param logoUrl logo地址
+	 * @return
+	 */
+	public String getBase64QRCode(String content, String logoUrl) {
+		return getBase64Image(content, WIDTH, HEIGHT, logoUrl, LOGO_WIDTH, LOGO_HEIGHT);
+	}
+
+	/**
+	 * 生成二维码
+	 *
+	 * @param content    内容
+	 * @param width      二维码宽度
+	 * @param height     二维码高度
+	 * @param logoUrl    logo 在线地址
+	 * @param logoWidth  logo 宽度
+	 * @param logoHeight logo 高度
+	 * @return
+	 */
+	public String getBase64QRCode(String content, Integer width, Integer height, String logoUrl, Integer logoWidth, Integer logoHeight) {
+		return getBase64Image(content, width, height, logoUrl, logoWidth, logoHeight);
+	}
+
+	private String getBase64Image(String content, Integer width, Integer height, String logoUrl, Integer logoWidth, Integer logoHeight) {
+		ByteArrayOutputStream os = new ByteArrayOutputStream();
+		BufferedImage bufferedImage = crateQRCode(content, width, height, logoUrl, logoWidth, logoHeight);
+		try {
+			ImageIO.write(bufferedImage, IMAGE_FORMAT, os);
+		} catch (IOException e) {
+			log.error("[生成二维码,错误{}]", e);
+		}
+		// 转出即可直接使用
+		return String.format(BASE64_IMAGE, Base64.encode(os.toByteArray()));
+	}
+
+
+	/**
+	 * 生成二维码
+	 *
+	 * @param content    内容
+	 * @param width      二维码宽度
+	 * @param height     二维码高度
+	 * @param logoUrl    logo 在线地址
+	 * @param logoWidth  logo 宽度
+	 * @param logoHeight logo 高度
+	 * @return
+	 */
+	private BufferedImage crateQRCode(String content, Integer width, Integer height, String logoUrl, Integer logoWidth, Integer logoHeight) {
+		if (StrUtil.isNotBlank(content)) {
+			ServletOutputStream stream = null;
+			HashMap<EncodeHintType, Comparable> hints = new HashMap<>(4);
+			// 指定字符编码为utf-8
+			hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
+			// 指定二维码的纠错等级为中级
+			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
+			// 设置图片的边距
+			hints.put(EncodeHintType.MARGIN, 2);
+			try {
+				QRCodeWriter writer = new QRCodeWriter();
+				BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
+				BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+				for (int x = 0; x < width; x++) {
+					for (int y = 0; y < height; y++) {
+						bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
+					}
+				}
+				if (StrUtil.isNotBlank(logoUrl)) {
+					insertLogo(bufferedImage, width, height, logoUrl, logoWidth, logoHeight);
+				}
+				return bufferedImage;
+			} catch (Exception e) {
+				e.printStackTrace();
+			} finally {
+				if (stream != null) {
+					try {
+						stream.flush();
+						stream.close();
+					} catch (IOException e) {
+						e.printStackTrace();
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * 二维码插入logo
+	 *
+	 * @param source     二维码
+	 * @param width      二维码宽度
+	 * @param height     二维码高度
+	 * @param logoUrl    logo 在线地址
+	 * @param logoWidth  logo 宽度
+	 * @param logoHeight logo 高度
+	 * @throws Exception
+	 */
+	private void insertLogo(BufferedImage source, Integer width, Integer height, String logoUrl, Integer logoWidth, Integer logoHeight) throws Exception {
+		// logo 源可为 File/InputStream/URL
+		Image src = ImageIO.read(new URL(logoUrl));
+		// 插入LOGO
+		Graphics2D graph = source.createGraphics();
+		int x = (width - logoWidth) / 2;
+		int y = (height - logoHeight) / 2;
+		graph.drawImage(src, x, y, logoWidth, logoHeight, null);
+		Shape shape = new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 6, 6);
+		graph.setStroke(new BasicStroke(3f));
+		graph.draw(shape);
+		graph.dispose();
+	}
+
+
+	/**
+	 * 获取二维码
+	 *
+	 * @param content 内容
+	 * @param output  输出流
+	 * @throws IOException
+	 */
+	public void getQRCode(String content, OutputStream output) throws IOException {
+		BufferedImage image = crateQRCode(content, WIDTH, HEIGHT, null, null, null);
+		ImageIO.write(image, IMAGE_FORMAT, output);
+	}
+
+	/**
+	 * 获取二维码
+	 *
+	 * @param content 内容
+	 * @param logoUrl logo资源
+	 * @param output  输出流
+	 * @throws Exception
+	 */
+	public void getQRCode(String content, String logoUrl, OutputStream output) throws Exception {
+		BufferedImage image = crateQRCode(content, WIDTH, HEIGHT, logoUrl, LOGO_WIDTH, LOGO_HEIGHT);
+		ImageIO.write(image, IMAGE_FORMAT, output);
+	}
+
+	/**
+	 *高度——height,
+	 * 宽度——width,
+	 * 二维码内容——text(url需要自动跳转前面加上https://)
+	 */
+	public static byte[] getQRCodeImage(String text, int width, int height) throws WriterException, IOException {
+		QRCodeWriter qrCodeWriter = new QRCodeWriter();
+
+		HashMap<EncodeHintType, Object> hints = new HashMap<>();
+		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
+
+		BitMatrix bitMatrix =qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height,hints);
+		//删除白边
+//		BufferedImage bufferedImage = deleteWhite(bitMatrix);
+
+		//BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height);
+
+		ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
+		MatrixToImageWriter.writeToStream(bitMatrix, "JPG", pngOutputStream);
+		//返回
+		return pngOutputStream.toByteArray();
+	}
+
+	/**
+	 * 去白边的话,调用这个方法
+	 * @param matrix
+	 * @return
+	 */
+	private static BufferedImage  deleteWhite(BitMatrix matrix) {
+		int[] rec = matrix.getEnclosingRectangle();
+		int resWidth = rec[2] + 1;
+		int resHeight = rec[3] + 1;
+
+		BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
+		resMatrix.clear();
+		for (int i = 0; i < resWidth; i++) {
+			for (int j = 0; j < resHeight; j++) {
+				if (matrix.get(i + rec[0], j + rec[1]))
+					resMatrix.set(i, j);
+			}
+		}
+
+		int width = resMatrix.getWidth();
+		int height = resMatrix.getHeight();
+		BufferedImage image = new BufferedImage(width, height,
+			BufferedImage.TYPE_INT_RGB);
+		for (int x = 0; x < width; x++) {
+			for (int y = 0; y < height; y++) {
+				image.setRGB(x, y, resMatrix.get(x, y) ? BLACK
+					: WHITE);
+			}
+		}
+		return image;
+	}
+
+
+//	private static BitMatrix deleteWhite(BitMatrix matrix) {
+//		int[] rec = matrix.getEnclosingRectangle();
+//		int resWidth = rec[2] + 1;
+//		int resHeight = rec[3] + 1;
+//
+//		BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
+//		resMatrix.clear();
+//		for (int i = 0; i < resWidth; i++) {
+//			for (int j = 0; j < resHeight; j++) {
+//				if (matrix.get(i + rec[0], j + rec[1]))
+//					resMatrix.set(i, j);
+//			}
+//		}
+//		return resMatrix;
+//	}
+
+}
diff --git a/src/main/java/org/springblade/modules/qrcode/QrCodeController.java b/src/main/java/org/springblade/modules/qrcode/QrCodeController.java
new file mode 100644
index 0000000..e8d02ca
--- /dev/null
+++ b/src/main/java/org/springblade/modules/qrcode/QrCodeController.java
@@ -0,0 +1,107 @@
+package org.springblade.modules.qrcode;
+
+import com.google.zxing.WriterException;
+import lombok.AllArgsConstructor;
+import org.springblade.common.utils.QRCodeUtil;
+import org.springblade.modules.system.entity.User;
+import org.springblade.modules.system.service.IUserService;
+import org.springblade.modules.system.vo.UserVO;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import sun.misc.BASE64Encoder;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+/**
+ * @author zhongrj
+ * @date 2021-08-24
+ * 二维码生成
+ */
+@RestController
+@RequestMapping("/qrCode")
+@AllArgsConstructor
+public class QrCodeController {
+
+	private final IUserService userService;
+
+	/**
+	 * 二维码生成-字节流
+	 * @param securityNumber 保安证编号
+	 * @return
+	 */
+	@GetMapping("/getQrCode")
+	public ResponseEntity<byte[]> getQrCode(String securityNumber) throws UnsupportedEncodingException {
+		String url = "http://61.131.136.25:2080/securityInfo.html";
+		if (null!=securityNumber) {
+			String encoded = URLEncoder.encode(securityNumber,"UTF-8");
+			String content = url + "?securityNumber=" + encoded;
+			ResponseEntity<byte[]> aEntity = null;
+			try {
+				URLEncoder.encode(content,"utf-8");
+				byte[] qrCodeImage = QRCodeUtil.getQRCodeImage(content, 350, 350);
+
+				// Set headers
+				final HttpHeaders headers = new HttpHeaders();
+				headers.setContentType(MediaType.IMAGE_PNG);
+				aEntity = new ResponseEntity<byte[]>(qrCodeImage, headers, HttpStatus.CREATED);
+			} catch (WriterException e) {
+				e.printStackTrace();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			return aEntity;
+		}
+		return null;
+	}
+
+
+	/**
+	 * 二维码生成base64
+	 * @param code 溯源码编号
+	 * @return
+	 */
+	@GetMapping("/getQrCodeBase64")
+	public String getQrCodeBase64(String code) throws Exception{
+		String url = "http://61.131.136.25:2080/securityInfo.html";
+		if (null!=code) {
+			String encoded = URLEncoder.encode(code,"UTF-8");
+			String content = url + "?code=" + encoded;
+			byte[] qrCodeImage = QRCodeUtil.getQRCodeImage(content, 350, 350);
+			String encode = new BASE64Encoder().encode(qrCodeImage);
+			return "data:image/png;base64,"+encode;
+		}
+		return null;
+	}
+
+
+	/**
+	 * 二维码生成base64
+	 * @param securityNumber 保安证编号
+	 * @return
+	 */
+	@GetMapping("/getQrCodeDown")
+	public String getQrCodeDown(String securityNumber) throws Exception{
+//		String url = "http://s16s652780.51mypc.cn/securityInfo/securityInfo.html";
+		String url = "http://61.131.136.25:2080/securityInfo.html";
+		if (null!=securityNumber) {
+			String encoded = URLEncoder.encode(securityNumber,"UTF-8");
+			String content = url + "?securityNumber=" + encoded;
+			byte[] qrCodeImage = QRCodeUtil.getQRCodeImage(content, 350, 350);
+			String path = "D:\\QrCode\\";
+			FileOutputStream fileOutputStream = new FileOutputStream(path+securityNumber+".png");
+			fileOutputStream.write(qrCodeImage,0,qrCodeImage.length);
+			fileOutputStream.flush();
+			fileOutputStream.close();
+			return securityNumber;
+		}
+		return null;
+	}
+
+}

--
Gitblit v1.9.3