Java生成二维码并把图片流导出压缩包下载(亲测可用)

目录

背景

Maven依赖相关

二维码生成

        基础实体类

        二维码工具类 

        控制层代码

结果展示

        单个二维码

        二维码压缩包

源码地址


背景:

                实际开发中有不少二维码生成并下载的需求,单个和批量下载都比较常见,最近又来了这种需求,决定记录一下,文末附上源码。

Maven依赖相关:

<!--二维码-->
  <dependency>
       <groupId>com.google.zxing</groupId>
       <artifactId>core</artifactId>
       <version>3.1.0</version>
  </dependency>
  <dependency>
       <groupId>com.google.zxing</groupId>
       <artifactId>javase</artifactId>
       <version>3.1.0</version>
   </dependency>
<!--Lombok-->
  <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <version>1.18.4</version>
  </dependency>

二维码生成:

        基础实体类:

package com.example.qrcode.util;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.HashMap;

/**
 * @author yellow duck
 * @date 2022-04-08 14:41
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class QrCodeInfo {
    /**
     * 图片信息 示例:key - 二维码编号:  value - 0000001(具体的值)
     * */
    private HashMap<String, String> textMap;
    /**
     * 二维码信息
     * */
    private String info;
}

        二维码工具类 :

package com.example.qrcode.util;

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 javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.google.zxing.client.j2se.MatrixToImageConfig.BLACK;
import static com.google.zxing.client.j2se.MatrixToImageConfig.WHITE;

/**
 * 二维码相关工具类
 *
 * @author yellow duck
 * @date 2022-04-08 14:34
 */
public class QrCodeUtil {
    /**
     * 二维码宽和高
     */
    private static final int WIDTH_AND_HEIGHT = 180;
    /**
     * 文字的X轴坐标
     */
    private static final int TEXT_X = 200;
    /**
     * 文字的Y轴坐标
     */
    private static int TEXT_Y = 80;
    /**
     * 文字的段落高度
     */
    private static final int SPACE_Y = 40;
    /**
     * 二维码参数设置
     */
    private static final Map<EncodeHintType, Object> HINTS;

    static {
        HINTS = new EnumMap<>(EncodeHintType.class);
        //设置编码
        HINTS.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        //设置二维码的纠错级别
        HINTS.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
    }

    /**
     * 绘制二维码并返回图片流
     *
     * @param qrcode: 二维码相关信息
     * @date 2022/4/8 14:44
     * @author YD
     */
    public static BufferedImage createQrCode(QrCodeInfo qrcode) throws WriterException {
        //设置对象并生成二维码
        BitMatrix bitMatrix = new MultiFormatWriter().encode(qrcode.getInfo(), BarcodeFormat.QR_CODE, WIDTH_AND_HEIGHT, WIDTH_AND_HEIGHT, HINTS);
        //创建二维码图片缓冲区
        BufferedImage image = new BufferedImage(WIDTH_AND_HEIGHT, WIDTH_AND_HEIGHT, BufferedImage.TYPE_INT_RGB);
        //生成二维码数组
        for (int x = 0; x < bitMatrix.getWidth(); x++) {
            for (int y = 0; y < bitMatrix.getHeight(); y++) {
                //二维坐标整个区域:画什么颜色
                image.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
            }
        }
        //觉得这个字体好看一些 如果不喜欢可以换成微软雅黑 Font.BOLD为加粗 但会出现锯齿
        Font fontChinese = new Font("华文细黑", Font.PLAIN, 16);
        //创建画布的缓冲区
        BufferedImage bufferedImage = new BufferedImage(600, 240, BufferedImage.TYPE_4BYTE_ABGR);

        //创建画布
        Graphics2D g2d = bufferedImage.createGraphics();
        //设置背景颜色
        g2d.setBackground(Color.WHITE);
        //开启文字抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //绘制二维码
        g2d.drawImage(image, 10, 30, image.getWidth(), image.getHeight(), null);
        //设置画笔颜色
        g2d.setColor(Color.BLACK);
        ///设置二维码文本字体
        g2d.setFont(fontChinese);
        //绘制文字
        HashMap<String, String> textMap = qrcode.getTextMap();
        //填充文字
        textMap.forEach((key, value) -> {
            //每次间距为40 可以根据具体调整
            g2d.drawString(key + value, TEXT_X, TEXT_Y);
            TEXT_Y += SPACE_Y;
        });
        //恢复Y轴坐标
        TEXT_Y = 80;
        //销毁画笔
        g2d.dispose();
        bufferedImage.flush();
        image = bufferedImage;
        return image;
    }


    /**
     * 把生成的二维码打进压缩包并下载
     *
     * @param images: 二维码流集合
     * @date 2022/4/8 15:26
     * @author YD
     */
    public static void compressQrCodeToZip(List<BufferedImage> images, HttpServletResponse httpServletResponse) throws IOException {
        //重置HttpServletResponse防止乱码
        httpServletResponse.reset();
        ZipOutputStream zos = new ZipOutputStream(httpServletResponse.getOutputStream());
        //文件的名称
        String downloadFilename = "二维码压缩包.zip";
        //转换中文否则可能会产生乱码
        downloadFilename = URLEncoder.encode(downloadFilename, "UTF-8");
        // 指明response的返回对象是文件流
        httpServletResponse.setContentType("application/octet-stream; charset=UTF-8");
        //设置下载格式和名称
        httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename);
        //添加二维码进zip压缩包
        images.forEach(
                image -> {
                    try {
                        byte[] buf = new byte[8192];
                        int len;
                        //添加二维码进zip
                        ZipEntry entry = new ZipEntry(UUID.randomUUID() + ".png");
                        zos.putNextEntry(entry);
                        InputStream inputStream = bufferedImageToInputStream(image);
                        //输出压缩包
                        while ((len = inputStream.read(buf)) > 0) {
                            zos.write(buf, 0, len);
                        }
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
        );
        zos.close();
    }

    /**
     * 下载单个二维码
     *
     * @param bufferedImage:       二维码流
     * @param httpServletResponse: http响应
     * @date 2022/4/8 15:37
     * @author YD
     */
    public static void singleQrCode(BufferedImage bufferedImage, HttpServletResponse httpServletResponse) throws IOException {
        //重置HttpServletResponse防止乱码
        httpServletResponse.reset();
        //文件的名称
        String downloadFilename = UUID.randomUUID() + ".png";
        //转换中文否则可能会产生乱码
        downloadFilename = URLEncoder.encode(downloadFilename, "UTF-8");
        // 指明response的返回对象是文件流
        httpServletResponse.setContentType("application/octet-stream; charset=UTF-8");
        //设置下载格式和名称
        httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename);
        //输出二维码到前端
        ImageIO.write(bufferedImage, "png", httpServletResponse.getOutputStream());
    }

    /**
     * 将BufferedImage转换为InputStream
     *
     * @param image: 图片流
     * @date 2022/4/8 15:29
     * @author YD
     */
    public static InputStream bufferedImageToInputStream(BufferedImage image) throws IOException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(image, "png", os);
        try (InputStream input = new ByteArrayInputStream(os.toByteArray())) {
            return input;
        }
    }


}

        控制层代码:

package com.example.qrcode.controller;

import com.example.qrcode.util.QrCodeInfo;
import com.google.zxing.WriterException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.example.qrcode.util.QrCodeUtil.*;

/**
 * 二维码生成控制器
 *
 * @author yellow duck
 * @date 2022-04-08 15:41
 */
@RestController
@RequestMapping("qrcode")
public class QrCodeController {
    @GetMapping("downloadZip")
    public void downloadZip(HttpServletResponse httpServletResponse) throws IOException {
        List<BufferedImage> bufferedImages = new ArrayList<>();
        //这里把需要生成的二维码然后添加进bufferedImages集合里
        compressQrCodeToZip(bufferedImages,httpServletResponse);
    }

    @GetMapping("downloadOne")
    public void downloadOne(HttpServletResponse httpServletResponse) throws IOException, WriterException {
        HashMap<String, String> textMap = new HashMap<>();
        textMap.put("编号:","000001");
        textMap.put("名称:","二维码");
        BufferedImage bufferedImages = createQrCode(QrCodeInfo.builder()
                .info("二维码的内容")
                .textMap(textMap)
                .build());
        singleQrCode(bufferedImages,httpServletResponse);
    }
}

结果展示:

        单个二维码:

         二维码压缩包:

源码地址:

SpringBoot生成二维码单个下载和打包下载。-Java文档类资源-CSDN下载https://download.csdn.net/download/weixin_40579395/85094823

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小黄鸭技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值