123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- package com.iotechn.unimall.data.util;
- import com.aliyun.oss.OSSClient;
- import com.aliyun.oss.model.ObjectMetadata;
- import com.aliyun.oss.model.PutObjectRequest;
- import com.google.zxing.BarcodeFormat;
- import com.google.zxing.EncodeHintType;
- 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 lombok.Getter;
- import lombok.SneakyThrows;
- import org.apache.http.entity.ContentType;
- import org.springframework.beans.factory.InitializingBean;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.core.io.ClassPathResource;
- import org.springframework.mock.web.MockMultipartFile;
- import org.springframework.stereotype.Component;
- import org.springframework.util.StringUtils;
- import org.springframework.web.multipart.MultipartFile;
- import sun.font.FontDesignMetrics;
- import javax.imageio.ImageIO;
- import java.awt.*;
- import java.awt.font.FontRenderContext;
- import java.awt.font.LineMetrics;
- import java.awt.geom.RoundRectangle2D;
- import java.awt.image.BufferedImage;
- import java.io.*;
- import java.nio.charset.StandardCharsets;
- import java.nio.file.FileSystems;
- import java.nio.file.Path;
- import java.util.HashMap;
- import java.util.Hashtable;
- import java.util.Properties;
- /**
- * @Author:chengchangjiang
- * @Description: 二维码Util类
- * @Date:Created in 9:38 2021-09-03
- */
- @Component
- public class QRCodeUtil implements InitializingBean {
- @Value("${oss.aliyun.oss.basekUrl}")
- private String baseUrl;
- @Value("${oss.aliyun.oss.bucket}")
- private String bucket;
- @Autowired
- private OSSClient ossClient;
- @Value("${oss.aliyun.oss.endpoint}")
- private String endpoint;
- private String host;
- @Override
- public void afterPropertiesSet() throws Exception {
- host = "http://" + bucket + "." + endpoint;
- }
- /***
- * 生成二维码图片并上传OSS
- * @param text 二维码内容
- * @param width 宽度
- * @param height 高度
- * @param type 类型
- * @param name 图片名字
- * @return
- */
- public String generateQRCodeImage(String text, int width, int height,String type,String name){
- try {
- QRCodeWriter qrCodeWriter = new QRCodeWriter();
- Hashtable<EncodeHintType, Object> hints = new Hashtable();
- hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
- BitMatrix bitMatrix = qrCodeWriter.encode(type+"="+text, BarcodeFormat.QR_CODE, width, height,hints);
- File file = new File( new String(("templates" + File.separator + name+".png").getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));
- if(!file.exists()){
- boolean flag = file.mkdirs();
- }
- Path path = FileSystems.getDefault().getPath(file.getAbsoluteFile().getPath());
- MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);
- FileInputStream fileInputStream = new FileInputStream(file.getAbsoluteFile());
- MultipartFile multipartFile = new MockMultipartFile( ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
- String result = upload(multipartFile,name);
- file.delete();
- return result;
- }
- catch (Exception e){
- System.out.println("二维码异常:"+e.toString());
- return "error";
- }
- }
- /**
- * 后台通过服务器间接传文件
- * @param file
- * @return
- * @throws IOException
- */
- public String upload(MultipartFile file, String sendCarNo) throws IOException {
- ObjectMetadata objectMetadata = new ObjectMetadata();
- objectMetadata.setContentLength(file.getSize());
- objectMetadata.setContentType(file.getContentType());
- PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, "QRCode/" +sendCarNo+".png", file.getInputStream(), objectMetadata);
- ossClient.putObject(putObjectRequest);
- return baseUrl + "QRCode/" + sendCarNo+".png";
- }
- private static final int QRCODE_SIZE = 320; // 二维码尺寸,宽度和高度均是320
- private static final String FORMAT_TYPE = "PNG"; // 二维码图片类型
- // //1、生成带logo和底部文字得二维码
- // @SneakyThrows
- // @GetMapping("/getQrCode1")
- // public void getQrCode1(HttpServletResponse response) {
- // ServletOutputStream os = response.getOutputStream();
- // BufferedImage bufferedImage = QRCodeUtil.getQRCodeImage("test", "底部文字");
- // response.setContentType("image/png");
- // ImageIO.write(bufferedImage,"png",os);
- // }
- // //2、生成不带logo和底部文字得二维码
- // @SneakyThrows
- // @GetMapping("/getQrCode2")
- // public void getQrCode2(HttpServletResponse response) {
- // ServletOutputStream os = response.getOutputStream();
- // BufferedImage bufferedImage = QRCodeUtil.getQRCodeImage("test", false);
- // response.setContentType("image/png");
- // ImageIO.write(bufferedImage,"png",os);
- // }
- // //3、生成默认带logo不带底部文字得二维码
- // @SneakyThrows
- // @GetMapping("/getQrCode3")
- // public void getQrCode3(HttpServletResponse response) {
- // ServletOutputStream os = response.getOutputStream();
- // BufferedImage bufferedImage = QRCodeUtil.generateQRCodeImage("test");
- // response.setContentType("image/png");
- // ImageIO.write(bufferedImage,"png",os);
- // }
- // //3、生成不带logo带底部文字得二维码
- // @SneakyThrows
- // public getQrCode3(HttpServletResponse response) {
- // ServletOutputStream os = response.getOutputStream();
- // BufferedImage bufferedImage = QRCodeUtil.getQRCodeImage("test",false,
- // "底部文字");
- // response.setContentType("image/png");
- // ImageIO.write(bufferedImage,"png",os);
- // }
- /**
- * 获取二维码图片
- *
- * @param dataStr 二维码内容
- * @param needLogo 是否需要添加logo
- * @param bottomText 底部文字 为空则不显示
- * @return
- */
- @SneakyThrows
- public String getQRCodeImage(String dataStr, boolean needLogo, String bottomText ,String name) {
- if (dataStr == null) {
- throw new RuntimeException("未包含任何信息");
- }
- HashMap<EncodeHintType, Object> hints = new HashMap<>();
- hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); //定义内容字符集的编码
- hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); //定义纠错等级
- hints.put(EncodeHintType.MARGIN, 1);
- QRCodeWriter qrCodeWriter = new QRCodeWriter();
- BitMatrix bitMatrix = qrCodeWriter.encode(dataStr, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
- int width = bitMatrix.getWidth();
- int height = bitMatrix.getHeight();
- int tempHeight = height;
- if (StringUtils.hasText(bottomText)) {
- tempHeight = tempHeight + 12;
- }
- BufferedImage image = new BufferedImage(width, tempHeight, BufferedImage.TYPE_INT_RGB);
- for (int x = 0; x < width; x++) {
- for (int y = 0; y < height; y++) {
- image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
- }
- }
- // 判断是否添加logo
- if (needLogo) {
- insertLogoImage(image);
- }
- // 判断是否添加底部文字
- if (StringUtils.hasText(bottomText)) {
- addFontImage(image, bottomText);
- }
- File file = new File( new String(("templates" + File.separator + name+".png").getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));
- if(!file.exists()){
- boolean flag = file.mkdirs();
- }
- Path path = FileSystems.getDefault().getPath(file.getAbsoluteFile().getPath());
- // ByteArrayOutputStream out = new ByteArrayOutputStream();
- // ImageIO.write(image,"png",path);
- // MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);
- //创建一个ByteArrayOutputStream
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- //把BufferedImage写入ByteArrayOutputStream
- ImageIO.write(image, "png", os);
- //ByteArrayOutputStream转成InputStream
- InputStream input = new ByteArrayInputStream(os.toByteArray());
- //InputStream转成MultipartFile
- MultipartFile multipartFile =new MockMultipartFile("file", "file.jpg", "text/plain", input);
- // FileInputStream fileInputStream = new FileInputStream(file.getAbsoluteFile());
- // MultipartFile multipartFile = new MockMultipartFile( ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
- String result = upload(multipartFile,name);
- file.delete();
- return result;
- }
- /**
- * 插入logo图片
- *
- * @param source 二维码图片
- * @throws Exception
- */
- private static void insertLogoImage(BufferedImage source) throws Exception {
- // 默认logo放于resource/static/image目录下
- ClassPathResource classPathResource = new ClassPathResource("static/image/logo.png");
- InputStream inputStream = classPathResource.getInputStream();
- if (inputStream == null || inputStream.available() == 0) {
- return;
- }
- Image src = ImageIO.read(inputStream);
- int width = 30;
- int height = 30;
- 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;
- // 插入LOGO
- Graphics2D graph = source.createGraphics();
- int x = (QRCODE_SIZE - width) / 2;
- int y = (QRCODE_SIZE - height) / 2;
- graph.drawImage(src, x, y, width, height, null);
- Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
- graph.setStroke(new BasicStroke(3f));
- graph.draw(shape);
- graph.dispose();
- }
- private static void addFontImage(BufferedImage source, String declareText) {
- //生成image
- int defineWidth = QRCODE_SIZE;
- int defineHeight = 20;
- BufferedImage textImage = new BufferedImage(defineWidth, defineHeight, BufferedImage.TYPE_INT_RGB);
- Graphics2D g2 = (Graphics2D) textImage.getGraphics();
- //开启文字抗锯齿
- g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
- g2.setBackground(Color.WHITE);
- g2.clearRect(0, 0, defineWidth, defineHeight);
- g2.setPaint(Color.BLACK);
- FontRenderContext context = g2.getFontRenderContext();
- String font_cn = getChineseFont();
- //部署linux需要注意 linux无此字体会显示方块
- Font font = new Font("宋体", Font.BOLD, 18);
- g2.setFont(font);
- LineMetrics lineMetrics = font.getLineMetrics(declareText, context);
- FontMetrics fontMetrics = FontDesignMetrics.getMetrics(font);
- float offset = (defineWidth - fontMetrics.stringWidth(declareText)) / 2;
- float y = (defineHeight + lineMetrics.getAscent() - lineMetrics.getDescent() - lineMetrics.getLeading()) / 2;
- g2.drawString(declareText, (int) offset, (int) y);
- Graphics2D graph = source.createGraphics();
- //开启文字抗锯齿
- graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
- //添加image
- int width = textImage.getWidth(null);
- int height = textImage.getHeight(null);
- Image src = textImage;
- graph.drawImage(src, 0, QRCODE_SIZE - 8, width, height, Color.WHITE, null);
- graph.dispose();
- }
- /**
- * 获取中文字体位置
- *
- * @return
- * @author xxj 2017年4月28日
- */
- private static String getChineseFont() {
- //宋体(对应css中的 属性 font-family: SimSun; /*宋体*/)
- String font1 = "templates" + File.separator + "msyh.ttc";
- // String font1 = "templates" + File.separator + "simsun.ttf";
- //判断系统类型,加载字体文件
- Properties prop = System.getProperties();
- String osName = prop.getProperty("os.name").toLowerCase();
- System.out.println(osName);
- if (osName.indexOf("linux") > -1) {
- font1 = "/usr/share/fonts/chinese/simsun.ttc";
- }
- else{
- font1 = "宋体";
- }
- return font1;
- }
- }
|