java二维码批量生成并打包为zip下载



import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.wxy.base.enumerate.HttpResult;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Author 
 * @Date: 2022/10/19 9:45
 */
public class QrcodeUtil {
    /**
     * 默认编码方式
     */
    public static final String DEFAULT_CHARSET = "UTF-8";
    /**
     * 默认二维码图片格式
     */
    public static final String DEFAULT_SUBFIX = "PNG";

    /**
     * 生成二维码默认宽度
     */
    public static final int DEFAULT_WIDTH = 250;
    /**
     * 生成二维码默认高度
     */
    public static final int DEFAULT_HEIGHT = 300;
    /**
     * 默认二维码中间log宽度
     */
    public static final int DEFAULT_LOG_WIDTH = 50;
    /**
     * 默认二维码中间log高度
     */
    public static final int DEFAULT_LOG_HEIGHT = 50;

    /**
     * log默认路径
     */
    public static final String DEFAULT_LOG_PATH = Objects.requireNonNull(QrcodeUtil.class.getClassLoader().getResource("log/company_logo.jpg")).getPath();

    /**
     * 由字符串生成二维码BufferedImage对象
     *
     * @param content 字符串内容
     * @param width   二维码宽度,如果为空或小于等于0采用默认宽度
     * @param height  二维码高度,如果为空或小于等于0采用默认高度
     * @return
     */
    private static BufferedImage createQrCodeBufferedImage(String content, Integer width, Integer height) throws WriterException {

        BufferedImage resultImage = null;
        if (!StringUtils.isEmpty(content)) {

            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, DEFAULT_CHARSET);// 指定字符编码为UTF-8
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 指定二维码的纠错等级为中级
            hints.put(EncodeHintType.MARGIN, 2);// 设置图片的边距

            QRCodeWriter writer = new QRCodeWriter();
            width = width != null && width > 0 ? width : DEFAULT_WIDTH;
            height = height != null && height > 0 ? height : DEFAULT_HEIGHT;

            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            // 写到字节数据中
            // MatrixToImageWriter.writeToStream(bitMatrix, DEFAULT_SUBFIX, os);
            // resultImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
            // ImageIO.write(resultImage, DEFAULT_SUBFIX, os);

            // 写到文件中
            // MatrixToImageWriter.writeToPath(bitMatrix, DEFAULT_SUBFIX,
            // Paths.get(DEFAULT_PATH));

            resultImage = new BufferedImage(bitMatrix.getWidth(), bitMatrix.getHeight(), BufferedImage.TYPE_INT_RGB);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
//                    resultImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF008000 : 0xFFFFFFFF);// 0xFF000000 黑色 0xFF008000 绿色
                    resultImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);// 0xFF000000 黑色 0xFFFFFFFF 白色
                }
            }
        }
        return resultImage;
    }


    /**
     * 由字符串生成base64格式的复杂二维码
     *
     * @param content        字符串内容
     * @param width          二维码宽度,如果为空或小于等于0采用默认宽度
     * @param height         二维码高度,如果为空或小于等于0采用默认高度
     * @param isSaveToPath   是否保存到文件中
     * @param logPath        log图片的路径
     * @param isFixedLogSize 是否固定log图片大小
     * @param text           二维码底部文本内容
     * @return
     */
    public static BufferedImage productQrCodeWithLog(String content, Integer width, Integer height, boolean isSaveToPath,
                                                     String logPath, boolean isFixedLogSize, String text) {


        if (StringUtils.isNotBlank(content)) {
            try {
                width = width != null && width > 0 ? width : DEFAULT_WIDTH;
                height = height != null && height > 0 ? height : DEFAULT_HEIGHT;
                BufferedImage image = createQrCodeBufferedImage(content, width, height);
                if (image != null) {
//                    ByteArrayOutputStream os = new ByteArrayOutputStream();
                    insertImageAndText(image, width, height, logPath, isFixedLogSize, text);
//                    ImageIO.write(image, DEFAULT_SUBFIX, os);
                    return image;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    /**
     * 插入LOGO
     *
     * @param source         二维码图片
     * @param width          二维码宽度,如果为空或小于等于0采用默认宽度
     * @param height         二维码高度,如果为空或小于等于0采用默认高度
     * @param imgPath        LOGO图片地址
     * @param isFixedLogSize 是否固定二维码中间log图标大小
     * @param text           二维码底部文本内容
     * @throws Exception
     */
    private static void insertImageAndText(BufferedImage source, Integer width, Integer height, String imgPath,
                                           boolean isFixedLogSize, String text) throws Exception {
        File file = new File(imgPath);
        if (!file.exists()) {
            System.err.println("" + imgPath + "   该文件不存在!");
            return;
        }
        Image src = ImageIO.read(new File(imgPath));
        int lwidth = src.getWidth(null);
        int lheight = src.getHeight(null);
        if (isFixedLogSize || lwidth >= width || lheight >= height) { // 固定LOGO大小
            if (lwidth > width) {
                lwidth = DEFAULT_LOG_WIDTH;
            }
            if (lheight > height) {
                lheight = DEFAULT_LOG_HEIGHT;
            }
            Image image = src.getScaledInstance(lwidth, lheight, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(lwidth, lheight, 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 = (width - lwidth) / 2;
        int y = (height - lheight) / 2;
        graph.drawImage(src, x, y, lwidth, lheight, null);
        Shape shape = new RoundRectangle2D.Float(x, y, lwidth, lheight, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);

        if (!StringUtils.isEmpty(text)) {
            int fontStyle = 1;
            int fontSize = 12; //
            // 计算文字开始的位置(居中显示)
            // x开始的位置:(图片宽度-字体大小*字的个数)/2
            int startX = (width - (fontSize * text.length())) / 2;
            // y开始的位置:图片高度-(图片高度-图片宽度)/2
            int startY = height - (height - width) / 2;
            graph.setColor(Color.BLUE);
            graph.setFont(new Font(null, fontStyle, fontSize)); // 字体风格与字体大小 graph.drawString(text, startX, startY);
            graph.drawString(text, startX, startY);
        }

        graph.dispose();
    }

    /**
     * 解码二维码内容
     *
     * @param file
     * @return
     * @throws Exception
     */
    public static String decode(File file) throws Exception {
        BufferedImage image;
        image = ImageIO.read(file);
        if (image == null) {
            return null;
        }
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Result result;
        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, DEFAULT_CHARSET);
        result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }

    /**
     * 生成多个二维码图片,压缩成zip写入响应流
     *
     * @param response    响应
     * @param contentList 二维码内容列表
     * @throws IOException
     */
    public static void downloadQrCodeZip(HttpServletResponse response, List<QrCodeContent> contentList) throws IOException {
        downloadQrCodeZip(response, contentList, "二维码.zip", DEFAULT_LOG_PATH, 400);
    }

    /**
     * 生成多个二维码图片,压缩成zip写入响应流
     *
     * @param response                  响应
     * @param contentList               二维码内容列表
     * @param downloadFileName          下载的zip文件名
     * @param logPath                   log路径
     * @param qrCodeImageWidthAndHeight 二维码宽高(是正方形的二维码,宽高一致)
     * @throws IOException
     */
    public static void downloadQrCodeZip(HttpServletResponse response,
                                         List<QrCodeContent> contentList,
                                         String downloadFileName,
                                         String logPath,
                                         int qrCodeImageWidthAndHeight
    ) throws IOException {

        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(downloadFileName, "UTF-8")); // 压缩包名

        try (ServletOutputStream outputStream = response.getOutputStream();
             ZipOutputStream zos = new ZipOutputStream(outputStream)) {

            if (CollectionUtils.isEmpty(contentList)) {
                return;
            }

            for (int i = 0; i < contentList.size(); i++) {
                QrCodeContent qrCodeContent = contentList.get(i);
                BufferedImage bufferedImage = productQrCodeWithLog(
                        qrCodeContent.getContent(),
                        qrCodeImageWidthAndHeight,
                        qrCodeImageWidthAndHeight,
                        false,
                        logPath,
                        true,
                        qrCodeContent.getTitle()
                );

                try (ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
                     ImageOutputStream imageOutputStream = new MemoryCacheImageOutputStream(byteOutputStream)) {

                    ImageIO.write(bufferedImage, qrCodeContent.getSuffix(), imageOutputStream);
                    zos.putNextEntry(new ZipEntry(qrCodeContent.getFileName()));
                    byte[] bytes = byteOutputStream.toByteArray();

                    zos.write(bytes);
                }

            }
        }
    }


    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class QrCodeContent {

        /**
         * 二维码内容(一般是url)
         */
        private String content;

        /**
         * 生成二维码图片的文件名(比如xxx.png或者xxx.jpeg)
         */
        private String fileName;

        /**
         * 二维码底部文本内容(可为空)
         */
        private String title;


        /**
         * 获取文件后缀
         *
         * @return
         */
        public String getSuffix() {
            int lastIndex = fileName.lastIndexOf(".");
            return fileName.substring(lastIndex + 1);
        }
    }


    /**
     * 生成多个二维码图片,压缩成zip写入响应流
     *
     * @param contentList 二维码内容列表
     * @throws IOException
     */
    public static void wriQrCodeZip(List<QrCodeContent> contentList) throws IOException {
        wriQrCodeZip(contentList, "二维码.zip", DEFAULT_LOG_PATH, 400);
    }


    public static void wriQrCodeZip(
            List<QrCodeContent> contentList,
            String downloadFileName,
            String logPath,
            int qrCodeImageWidthAndHeight
    ) throws IOException {


        try (
                ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
                ImageOutputStream imageOutputStream = new MemoryCacheImageOutputStream(byteOutputStream);
                FileOutputStream fileOutputStream = new FileOutputStream("\\Users\\18521\\Desktop\\r_code.zip");
                ZipOutputStream zos = new ZipOutputStream(fileOutputStream)
        ) {
            if (CollectionUtils.isEmpty(contentList)) {
                return;
            }

            for (int i = 0; i < contentList.size(); i++) {
                QrCodeContent qrCodeContent = contentList.get(i);
                BufferedImage bufferedImage = productQrCodeWithLog(
                        qrCodeContent.getContent(),
                        qrCodeImageWidthAndHeight,
                        qrCodeImageWidthAndHeight,
                        false,
                        logPath,
                        true,
                        qrCodeContent.getTitle()
                );

                ImageIO.write(bufferedImage, qrCodeContent.getSuffix(), imageOutputStream);
                zos.putNextEntry(new ZipEntry(qrCodeContent.getFileName()));
                byte[] bytes = byteOutputStream.toByteArray();

                zos.write(bytes);
            }


        }
    }


    public static void main(String[] args) throws IOException {

    }


}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
批量生成二维码打包,你可以使用以下步骤: 1. 安装 vue-qr 插件:在命令行中运行 `npm install vue-qr --save`,或者在项目目录下运行 `yarn add vue-qr`。 2. 创建一个二维码生成器组件:在 Vue 应用中创建一个新的组件,用于批量生成二维码。在组件中使用 vue-qr 插件来生成二维码。 3. 创建一个数据源:在组件中创建一个数据源,用于存储所有要生成二维码的数据。可以使用数组或对象存储数据。 4. 使用 v-for 指令循环生成二维码:在组件中使用 v-for 指令循环遍历数据源,使用 vue-qr 插件生成二维码,并将生成二维码添加到页面中。 5. 打包生成二维码:在组件中添加一个按钮,当用户点击按钮时,使用 jszip 插件将所有二维码打包成一个压缩文件,并将文件下载到本地。 以下是一个简单的示例代码: ```html <template> <div> <div v-for="(data, index) in dataSource" :key="index"> <p>{{ data.name }}</p> <qrcode :value="data.code"></qrcode> </div> <button @click="handleDownload">Download</button> </div> </template> <script> import VueQr from 'vue-qr' import JSZip from 'jszip' import FileSaver from 'file-saver' export default { components: { VueQr }, data() { return { dataSource: [ { name: 'Qrcode 1', code: 'https://www.example.com/1' }, { name: 'Qrcode 2', code: 'https://www.example.com/2' }, { name: 'Qrcode 3', code: 'https://www.example.com/3' } ] } }, methods: { handleDownload() { const zip = new JSZip() this.dataSource.forEach((data, index) => { const imgData = this.$refs[`qrcode${index}`][0].$el.toDataURL() zip.file(`${data.name}.png`, imgData.substr(imgData.indexOf(',') + 1), { base64: true }) }) zip.generateAsync({ type: 'blob' }).then((content) => { FileSaver.saveAs(content, 'qrcodes.zip') }) } } } </script> ``` 在上述示例代码中,我们使用了 vue-qr 插件来生成二维码,使用 jszip 插件将所有二维码打包成一个压缩文件,并使用 file-saver 插件将文件下载到本地。注意,我们使用了 $refs 来获取每个二维码组件的实例,并将实例转换为图片数据进行打包

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值