【Java】批量生成二维码图片并zip压缩下载

写在开头

在实际开发过程中,二维码生成和导出都是常见的功能,最近遇到一个批量生成二维码信息并根据批次号批量下载二维码图片的需求,这里记录一下下载二维码图片的源码。

所需依赖

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

源码

信息封装类

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

import java.awt.image.BufferedImage;

/**
 * 单个二维码的值和图片流信息
 *
 * @since 2023/5/10 13:11
 */

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class QrCodeInfo {

    /**
     * 二维码信息
     * 也用作文件名
     */
    private String qrCode;
    /**
     * 信息对应的二维码图片流
     */
    private BufferedImage image;

}

二维码生成 下载工具类


import cn.hutool.core.util.ObjectUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageConfig;
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.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 二维码相关 工具类
 * <p>
 *
 * @since 2023/5/10 13:09
 */
public class QrCodeUtils {

    /**
     * 二维码宽和高
     */
    private static final int WIDTH_AND_HEIGHT = 400;
    /**
     * 文字的X轴坐标
     */
    private static final int TEXT_X = 180;
    /**
     * 文字的Y轴坐标
     */
    private static final int TEXT_Y = 80;

    /**
     * 二维码参数设置
     */
    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 QrCodeInfo createQrCode(String qrcode) {
        try {
            //设置对象并生成二维码
            BitMatrix bitMatrix = new MultiFormatWriter().encode(qrcode, 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) ? MatrixToImageConfig.BLACK : MatrixToImageConfig.WHITE);
                }
            }

            //创建画布的缓冲区
            BufferedImage bufferedImage = new BufferedImage(WIDTH_AND_HEIGHT, WIDTH_AND_HEIGHT, 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);
            Font fontChinese = new Font("微软雅黑", Font.PLAIN, 16);
            ///设置二维码文本字体
            g2d.setFont(fontChinese);

            // 绘制文字(文字绘制在二维图图片的上方中间位置)
            g2d.drawString(qrcode, TEXT_X, TEXT_Y);

            //销毁画笔
            g2d.dispose();

            bufferedImage.flush();
            image = bufferedImage;
            return QrCodeInfo.builder().qrCode(qrcode).image(image).build();
        } catch (WriterException e) {
            e.printStackTrace();
            // 抛出异常了
            return null;
        }

    }

    /**
     * 将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;
        }
    }

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

    /**
     * 下载单个二维码
     *
     * @param qrCodeInfo:          二维码值和流信息
     * @param httpServletResponse: http响应
     * @date 2022/4/8 15:37
     * @author YD
     */
    public static void singleQrCode(QrCodeInfo qrCodeInfo, HttpServletResponse httpServletResponse) {
        if (ObjectUtil.isNotNull(qrCodeInfo)) {
            try {
                //重置HttpServletResponse防止乱码
                httpServletResponse.reset();
                //文件的名称
                String downloadFilename = qrCodeInfo.getQrCode() + ".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(qrCodeInfo.getImage(), "png", httpServletResponse.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Controller 层测试


import cn.hutool.core.util.ObjectUtil;
import com.wangzd.djframework.boot.common.core.util.qrcode.QrCodeInfo;
import com.wangzd.djframework.boot.common.core.util.qrcode.QrCodeUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 二维码 测试
 *
 * @author wangzhongdong
 * @since 2023/5/10 13:30
 */
@RestController
@RequestMapping("/qrCode")
public class QrCodeController {

    static String[] ARR = {"TA000001", "TA00000A",
            "TA00000B", "TA00002S",
            "TA00002T", "TA000032",
            "TA000033", "TA0000RS"};

    /**
     * 批量下载二维码
     *
     * @param httpServletResponse
     */
    @GetMapping("/downLoadZip")
    public void downLoadZip(HttpServletResponse httpServletResponse) {
        List<QrCodeInfo> qrCodeInfos = new ArrayList<>();
        for (String qrCode : ARR) {
            QrCodeInfo qrCodeInfo = QrCodeUtils.createQrCode(qrCode);
            if (ObjectUtil.isNotNull(qrCodeInfo)) {
                //这里把需要生成的二维码然后添加进bufferedImages集合里
                qrCodeInfos.add(qrCodeInfo);
            }
        }
        // 测试批量导出
        QrCodeUtils.compressQrCodeToZip(qrCodeInfos, 1111L httpServletResponse);
    }

    /**
     * 生成并下载单个二维码图片
     *
     * @param httpServletResponse
     */
    @GetMapping("downloadOne")
    public void downloadOne(HttpServletResponse httpServletResponse) {
        QrCodeInfo qrCodeInfo = QrCodeUtils.createQrCode(ARR[2]);
        // 测试单个导出
        QrCodeUtils.singleQrCode(qrCodeInfo, httpServletResponse);
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 要批量生成二维码zip文件,可以使用JavaScript编程语言来实现。 首先,我们需要安装一个适用于JavaScript的二维码库,例如qrcode.js。使用npm或者其他包管理工具进行安装。 接下来,我们需要引入所需的库文件,并创建一个HTML页面。在HTML页面中,我们需要添加一个表单,用于上传要生成二维码的文件。添加一个按钮,用于批量生成二维码。 在JavaScript代码中,我们需要监听表单的提交事件。当用户上传文件后,我们可以使用File API读取文件内容。如果文件是一个txt文件,并且每行包含一个URL,我们可以将行拆分为一个URL列表。 使用qrcode.js库,我们可以循环遍历URL列表,生成二维码,并将这些二维码存储在数组中。然后,我们可以使用jszip库创建一个zip文件,并将二维码添加到zip文件中。 最后,我们可以使用jszip库提供的方法将生zip文件下载到用户的计算机上,并提供一个合适的文件名。 总结起来,要实现批量生成二维码zip文件的功能,首先要使用qrcode.js库生成二维码,然后使用jszip库创建zip文件,最后将生zip文件提供给用户下载。 ### 回答2: JS 批量生成二维码zip,可以使用第三方库来实现。下面是一个使用 `jszip`、`qrcodejs` 和 `html2canvas` 库来实现的示例: 首先需要引入 `jszip`、`qrcodejs` 和 `html2canvas` 的库文件。然后在 HTML 文件中创建一个按钮,用于触发生成二维码zip的功能。 ```html <button onclick="generateQRCodes()">生成二维码zip</button> ``` 接下来是相关的 JavaScript 代码: ```javascript function generateQRCodes() { // 创建一个新的zip实例 var zip = new JSZip(); // 定义需要生成二维码的数据 var data = ['https://example.com/qrcode1', 'https://example.com/qrcode2', 'https://example.com/qrcode3']; // 定义生成二维码的参数 var options = { text: '', width: 128, height: 128, }; // 循环遍历数据生成二维码 data.forEach(function(url, index) { options.text = url; var qrCode = new QRCode(document.createElement('div'), options); // 使用 html2canvas 将二维码渲染为图片 html2canvas(qrCode._el.firstChild).then(function(canvas) { // 将图片添加到zip文件中 zip.file('qrcode' + (index + 1) + '.png', canvas.toDataURL().substr(22), { base64: true }); // 如果是最后一张二维码,则生zip文件并下载 if (index === data.length - 1) { zip.generateAsync({ type: "blob" }).then(function(content) { // 使用第三方库FileSaver保存并下载zip文件 saveAs(content, "qrcodes.zip"); }); } }); }); } ``` 上述代码首先定义了需要生成二维码的数据数组 `data`,然后通过循环遍历数组,在每次遍历中生一个二维码,并使用 `html2canvas` 将其渲染为图片图片被添加到 zip 文件中,并在最后一张二维码后将 zip 文件生下载到本地。 请注意,上述代码只是一个示例,具体使用时需要根据实际需求进行修改和适配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值