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

写在开头

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

所需依赖

		<dependency><groupId>com.google.zxinggroupId><artifactId>coreartifactId><version>3.5.1version>dependency><dependency><groupId>com.google.zxinggroupId><artifactId>javaseartifactId><version>3.5.1version>dependency><dependency><groupId>org.projectlombokgroupId><artifactId>lombokartifactId><version>1.18.4version>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;/*** 二维码相关 工具类* 

** @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;//添加二维码进zipZipEntry 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);}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部