记批量生成二维码并返回压缩包

添加依赖包---如果3.5.0用不了可以切换为3.4.1

<dependency>
	<groupId>com.google.zxing</groupId>
	<artifactId>core</artifactId>
	<version>3.5.0</version>
</dependency>
 <dependency>
	<groupId>com.google.zxing</groupId>
	<artifactId>javase</artifactId>
	<version>3.5.0</version>
</dependency>

生成总方法:

 public void generateQRCode(ParamVoList paramVoList, HttpServletResponse response) {
//获取所有的列表
List<Vo> voList=Mapper.queryList(paramVoList));
//开始生成二维码图片
 //重置HttpServletResponse防止乱码---未尝试
        response.reset();
//设置响应头
 response.setContentType("application/octet-stream");
// 设置压缩包名 这里直接用时间毫秒数
 response.setHeader("Content-Disposition", "attachment; filename=QrCode-" + System.currentTimeMillis() + ".zip");
//压缩包流读写
//这样写避免编码乱码问题----未尝试
//ZipOutputStream zipOut = new ZipOutputStream(fos, Charset.forName("utf-8"));
  ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(response.getOutputStream());
              //可选压缩等级
             //zos.setLevel(5);
            for (int j = 0; j < voList.size(); j++) {
                // 扫描的二维码字符串
                String codeString =voList.get(j).getId();
				//设置文字的编码格式 ---未尝试
				 codeString=URLEncoder.encode(codeString, "UTF-8");
                // 调用创建二维码方法生成二维码图片 QRCodeSize是二维码大小
                BufferedImage qrCode = createQrCode(codeString, 1500, "PNG",voList.get(j));
                // 将bufferedImage转成inputStream
                InputStream inputStream = bufferedImageToInputStream(qrCode);
                // 压缩文件名称 设置ZipEntry对象
                zos.putNextEntry(new ZipEntry(voList.get(j).getName() + ".PNG"));
                // 设置注释
                //zos.setComment("二维码");
                int temp = 0;
                // 读取内容
                while ((temp = inputStream.read()) != -1) {
                    // 压缩输出
                    zos.write(temp);
                }
                // 关闭输入流
                inputStream.close();
            }
        } catch (Exception e) {
             e.printStackTrace();
        }finally {
            try {
                if (null != zos) {
                    zos.flush();
                    zos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
	

生成包含字符串信息的二维码图片


    /**
     * 生成包含字符串信息的二维码图片
     *
     * @param content     二维码携带信息
     * @param qrCodeSize  二维码图片大小
     * @param imageFormat 二维码的格式
     */
    @SneakyThrows
    private static BufferedImage createQrCode(String content, int qrCodeSize, String imageFormat,Vo vo) {
        // 设置二维码纠错级别MAP
        Hashtable<EncodeHintType, Object> hintMap = new Hashtable<>();
		//设置编码格式 ----未尝试
		hintMap.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 矫错级别
        hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        //可以设置二维码图形边框值--即白边
        int margin=5;
        hintMap.put(EncodeHintType.MARGIN,margin);
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        // 创建比特矩阵(位矩阵)的QR码编码的字符串
        BitMatrix byteMatrix = qrCodeWriter.encode(content,BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hintMap);
        // 使BufferedImage勾画QRCode (matrixWidth 是行二维码像素点)
        int matrixWidth = byteMatrix.getWidth();
        int picWidth = matrixWidth - 200;
        // 去掉二维码的底部留白
        int picHeight = matrixWidth - 150;
        BufferedImage image = new BufferedImage(picWidth, picHeight, BufferedImage.TYPE_INT_RGB);
        image.createGraphics();
        Graphics2D graphics = (Graphics2D) image.getGraphics();
        // 以下开始画二维码
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, matrixWidth, matrixWidth);
        // 使用比特矩阵画并保存图像
        graphics.setColor(Color.BLACK);
        for (int i = 0; i < matrixWidth; i++) {
            for (int j = 0; j < matrixWidth; j++) {
                if (byteMatrix.get(i, j)) {
                    graphics.fillRect(i - 100, j - 100, 1, 1);
                }
            }
        }
        graphics.setColor(Color.BLACK);
        // 可以设置第一行底部文字
        Font font = new Font("微软雅黑", Font.BOLD, 45);
        graphics.setFont(font);
        // 消除文字锯齿
	graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        // 计算文字长度,计算居中的x点坐标
        FontMetrics fm = graphics.getFontMetrics(font);
        int textWidth = fm.stringWidth(vo.getName());
        int widthX = (picWidth - textWidth) / 2;
		//picHeight-100 是距离底部距离,如果不设置第二行文字则设置为picHeight-50刚好
        graphics.drawString(vo.getName(), widthX, picHeight-100);
        //此处设置第二行文字(可以省略)
        Font font2 = new Font("宋体", Font.PLAIN, 35);
        graphics.setFont(font2);
        // 消除文字锯齿
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        // 计算文字长度,计算居中的x点坐标
        FontMetrics fm2 = graphics.getFontMetrics(font);
        int textWidth2 = fm2.stringWidth(vo.getName());
        int widthX2 = (picWidth - textWidth2) / 2;
        graphics.drawString(vo.getSpaceTxt()+"-"+vo.getLocation(), widthX2, picHeight-50);
        graphics.dispose();

        // 设置二维码图片大小,并在底部加上字
        BufferedImage bufferedImage = resize(image, 500, 500);
        return bufferedImage;
    }

总绘制并设置图片大小与底部字体

    /**
     * 设置图片大小,并在底部加上字
     */
    private static BufferedImage resize(BufferedImage img, int newW, int newH) {
        Image tmp = img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH);
        BufferedImage dimg = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = dimg.createGraphics();
        g2d.drawImage(tmp, 0, 0, null);
        g2d.dispose();
        return dimg;
    }

工具类--将BufferedImage转换为InputStream

    /**
     * 将BufferedImage转换为InputStream
     * @param image
     * @return
     */
    private InputStream bufferedImageToInputStream(BufferedImage image){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "PNG", os);
            InputStream input = new ByteArrayInputStream(os.toByteArray());
            return input;
        } catch (IOException e) {
            logger.error("IOException" ,e);
        }
        return null;
    }

借鉴博主:

https://blog.csdn.net/weixin_40579395/article/details/124040713?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-2-124040713-blog-126057219.pc_relevant_multi_platform_whitelistv4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-2-124040713-blog-126057219.pc_relevant_multi_platform_whitelistv4&utm_relevant_index=3

https://www.cnblogs.com/lexus/archive/2012/03/02/2376831.html

注:原创作者:https://www.freesion.com/article/81151244727/