继续潜水

导航

 

二维码生成,普通的就不说了,问题就是需要再二维码中填写100-200的字的中文,奇葩需求对吧

文字过大会导致二维码过密,打印出来扫不出的问题

1:生成一个大的二维码

2:把这个二维码缩小到50*50,贴到pdf中

功能实现简单,做了一版加密的优化

image

 java通过加密,可以通过java解密,也可以通过html实现解密验证

package org.easwift.modules.online_doc.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import lombok.extern.slf4j.Slf4j;
import org.easwift.modules.admin.enums.FlowTypeEnum;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterOutputStream;

/**
 * @author tongzuqi
 * @create 2025/8/1 9:21 AM
 */
@Slf4j
public class QRCodeUtil {

    /**
     * 生成二维码图片(原始)
     * @param text  二维码内容
     * @param width 二维码宽度
     * @param height    二维码高度
     * @param margin    边框大小(默认为4)
     * @param filePath  文件路径
     * @throws WriterException
     * @throws IOException
     */
    public static void generateV1(String text,int width,int height,int margin,String filePath) throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, margin);
        BitMatrix bitMatrix = qrCodeWriter.encode(
                text,
                BarcodeFormat.QR_CODE,
                width,
                height,
                hints);
        MatrixToImageWriter.writeToPath(bitMatrix, "PNG", Paths.get(filePath));
    }

    /**
     * 生成二维码图片(压缩中文内容后生成二维码图片V2版本,压缩和解压方法需要配套使用
     * @param text  二维码内容
     * @param width 二维码宽度
     * @param height    二维码高度
     * @param margin    边框大小(默认为4)
     * @param filePath  文件路径
     * @throws WriterException
     * @throws IOException
     */
    public static void generateV2(String text,int width,int height,int margin,String filePath) throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, margin);
        text = compressChinese(text);
        log.info("generateV2压缩后内容:{}", text);
        log.info("generateV2解密后内容:{}", decompressChinese(text));
        BitMatrix bitMatrix = qrCodeWriter.encode(
                text,
                BarcodeFormat.QR_CODE,
                width,
                height,
                hints);
        MatrixToImageWriter.writeToPath(bitMatrix, "PNG", Paths.get(filePath));
    }

    public static String generateReport(QRCodeUtilGenerateFo qrCodeUtilGenerateFo){
        int index = 60;//字数截取
        String fileName = String.format("%s_%s.png",qrCodeUtilGenerateFo.getWtId(),System.currentTimeMillis());
        String filePath = qrCodeUtilGenerateFo.getFilePath() + "/qrCode/"+qrCodeUtilGenerateFo.getFlowTypeEnum().getCode()+"/"+fileName;
        String text = String.format("reportNo=%s&projectName=%s&requester=%s&sampleName=%s",
                qrCodeUtilGenerateFo.getReportNo(),
                qrCodeUtilGenerateFo.getProjectName().length() > index ? qrCodeUtilGenerateFo.getProjectName().substring(0,index) + "..." : qrCodeUtilGenerateFo.getProjectName(),
                qrCodeUtilGenerateFo.getRequester().length() > index ? qrCodeUtilGenerateFo.getRequester().substring(0,index) + "..." : qrCodeUtilGenerateFo.getRequester(),
                qrCodeUtilGenerateFo.getSampleName()
        );
        try {
            QRCodeUtil.generateV2(text,1000, 1000, 0,filePath);
            log.info("QRCodeUtil工具类, 生成报告二维码 : " + filePath);
            return filePath;
        } catch (WriterException e) {
            log.error("QRCodeUtil工具类, WriterException : " + e.getMessage());
        } catch (IOException e) {
            log.error("QRCodeUtil工具类, IOException :: " + e.getMessage());
        }
        return "";
    }


    public static void main(String[] args) {
//        // Try to generate a QR code image
//        try {
//            // Define the variables to be used in the QR code
//            String reportNo = "一二三四五六七八九十";
//            String reportId = "20";
//            String projectName = "一二三四五六七八九十";
//            String requester = "一二三四五六七八九十";
//            String sampleName = "一";
//            // Generate a file name using the current time
//            String fileName = String.format("%s_%s_%s.png",reportNo,reportId,System.currentTimeMillis());
//            // Define the file path
//            String filePath = "/Users/tongzuqi/Desktop/qrCode/"+fileName;
//            // Generate the text to be encoded in the QR code
//            String text = String.format("reportNo=%s&projectName=%s&requester=%s&sampleNo=%s",reportNo,projectName,requester,sampleName);
//            // Generate the QR code image
//            QRCodeUtil.generateV2(text,1000, 1000, 0,filePath);
//        } catch (WriterException e) {
//            // If a WriterException is thrown, print an error message
//            System.out.println("Could not generate QR Code, WriterException :: " + e.getMessage());
//        } catch (IOException e) {
//            // If an IOException is thrown, throw a RuntimeException
//            throw new RuntimeException(e);
//        }
        QRCodeUtil.generateReport(new QRCodeUtilGenerateFo().setFlowTypeEnum(FlowTypeEnum.ENTRUST).setFilePath("/Users/tongzuqi/Desktop")
                .setReportNo("XCBG-2025-04-21-001").setRequester("委托单位填写").setProjectName("测试项目名称40字显示测试项目名称40字显示测试项目名称40字显示测试项目名称40字显示测试项目名称40字显示测试项目名称往后隐藏123456").setWtId(11)
                .setSampleName("水泥")
        );
    }

    // 在生成二维码前压缩文本
    public static String compressChinese(String text) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (DeflaterOutputStream deflater = new DeflaterOutputStream(out, new Deflater(Deflater.BEST_COMPRESSION))) {
            deflater.write(text.getBytes(StandardCharsets.UTF_8));
        }
        return Base64.getUrlEncoder().withoutPadding().encodeToString(out.toByteArray());
    }
    // 解压方法(供扫描端使用)
    public static String decompressChinese(String compressed) throws IOException {
        byte[] data = Base64.getUrlDecoder().decode(compressed);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (InflaterOutputStream inflater = new InflaterOutputStream(out)) {
            inflater.write(data);
        }
        return new String(out.toByteArray(), StandardCharsets.UTF_8);
    }

}
View Code

html 验证

<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="UTF-8">  
    <title>文本解压工具</title>  
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pako/2.1.0/pako.min.js"></script>  
    <style>  
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }  
        textarea { width: 100%; height: 100px; margin: 10px 0; }  
        button { padding: 8px 15px; background: #4CAF50; color: white; border: none; cursor: pointer; }  
        button:hover { background: #45a049; }  
    </style>  
</head>  
<body>  
    <h1>文本解压工具</h1>  
    <p>输入压缩后的Base64 URL编码字符串:</p>  
    <textarea id="compressedInput" placeholder="请输入压缩后的文本..."></textarea>  
    <button onclick="decompress()">解压</button>  
    <p>解压结果:</p>  
    <textarea id="resultOutput" readonly></textarea>  

    <script>  
        function decompress() {  
            const compressedInput = document.getElementById('compressedInput').value.trim();  
            const resultOutput = document.getElementById('resultOutput');  
            
            if (!compressedInput) {  
                alert('请输入要解压的内容');  
                return;  
            }  

            try {  
                // 1. Base64 URL解码  
                const base64 = compressedInput  
                    .replace(/-/g, '+')  
                    .replace(/_/g, '/');  
                const binaryString = atob(base64);  
                const bytes = new Uint8Array(binaryString.length);  
                for (let i = 0; i < binaryString.length; i++) {  
                    bytes[i] = binaryString.charCodeAt(i);  
                }  

                // 2. 使用pako解压  
                const decompressed = pako.inflate(bytes, { to: 'string' });  

                // 3. 显示结果  
                resultOutput.value = decompressed;  
            } catch (e) {  
                resultOutput.value = '解压失败: ' + e.message;  
                console.error(e);  
            }  
        }  
    </script>  
</body>  
</html>
View Code

 

posted on 2025-08-07 16:43  继续潜水  阅读(13)  评论(0)    收藏  举报