@Override public void getQRCodeAsZip(String garbageRoomId, HttpServletResponse response) throws IOException { //根据roomid在MgtGarbageRoomWeightDeviceEntity中查找对应的imei LambdaQueryWrapper<MgtGarbageRoomWeightDeviceEntity> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(MgtGarbageRoomWeightDeviceEntity::getFkGarbageRoomId, garbageRoomId); List<MgtGarbageRoomWeightDeviceEntity> list = this.list(wrapper); String imei = new String(); for (MgtGarbageRoomWeightDeviceEntity mgtGarbageRoomWeightDeviceEntity : list) { imei = mgtGarbageRoomWeightDeviceEntity.getImei(); } //如果imei为空,则代表该条数据的imei的信息还未录入 if (StringUtils.isBlank(imei)) { throw new RenException("信息还未录入"); } //设置请求头 response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode("二维码", "UTF-8") + ".zip\""); response.setHeader("Content-Type", "application/zip"); //设置二维码的内容和logo内容 String baseUrlTemplate = "******"; String[] qrTexts = {"***", "***", "***"}; ByteArrayOutputStream zipOut = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(zipOut); try { for (int i = 0; i < 3; i++) { String url = String.format(baseUrlTemplate, garbageRoomId, imei) + i; BufferedImage qrCodeWithText = createQRCodeWithText(url, 200, 200, qrTexts[i]); ByteArrayOutputStream pngOut = new ByteArrayOutputStream(); ImageIO.write(qrCodeWithText, "PNG", pngOut); //设置压缩包内二维码名字 ZipEntry zipEntry = new ZipEntry("QRCode_" + qrTexts[i] + ".png"); zip.putNextEntry(zipEntry); zip.write(pngOut.toByteArray()); zip.closeEntry(); } } catch (Exception e) { //自定义异常 throw new RenException("下载附件失败", e); } finally { zip.close(); } IOUtils.copy(new ByteArrayInputStream(zipOut.toByteArray()), response.getOutputStream()); } public static BufferedImage createQRCodeWithText(String content, int width, int height, String text) throws Exception { Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); QRCodeWriter qrCodeWriter = new QRCodeWriter(); BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = (Graphics2D) image.getGraphics(); //消除文字锯齿 graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, width, height); // Draw text // 设置字体颜色和字体 graphics.setColor(new Color(230, 132, 73)); graphics.setFont(new Font("SansSerif", Font.BOLD, 18)); FontMetrics metrics = graphics.getFontMetrics(graphics.getFont()); // 计算文本的位置使其在图片中居中 int x = (width - metrics.stringWidth(text)) / 2; int y = ((height - metrics.getHeight()) / 2) + metrics.getAscent(); // 在图片中添加文本 graphics.drawString(text, x, y - 5); // Draw QR Code for (int xi = 0; xi < width; xi++) { for (int yi = 0; yi < height; yi++) { if (xi < x || xi > (x + metrics.stringWidth(text)) || yi < (y - metrics.getHeight()) || yi > y) { if (bitMatrix.get(xi, yi)) { image.setRGB(xi, yi, Color.BLACK.getRGB()); } else { image.setRGB(xi, yi, Color.WHITE.getRGB()); } } } } graphics.dispose(); return image; }
pom文件添加 <dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.1</version>
</dependency>
使用postman测试,直接生成的是乱码,需要将结果下载下来后查看
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = (Graphics2D) image.getGraphics();
这两行代码是Java中用于创建和操作图像的代码片段。
第一行代码创建了一个BufferedImage
对象,它是Java中表示图像的类。BufferedImage
是一个带有可访问的图像数据缓冲区的图像类,可以进行像素级别的读取和操作。
在该代码中,使用BufferedImage
类的构造函数创建了一个新的BufferedImage
对象,并传入了三个参数:width
、height
和BufferedImage.TYPE_INT_RGB
。其中,width
和height
是指定图像的宽度和高度,而BufferedImage.TYPE_INT_RGB
代表图像的颜色模型为RGB。
第二行代码获取了刚创建的BufferedImage
对象的图形上下文,并将其转换为Graphics2D
对象。通过image.getGraphics()
方法可以获得一个可用于绘制和操作图像的Graphics2D
对象。
Graphics2D
是Java中用于进行2D图形操作的类,它是Graphics
类的子类。通过获取到的Graphics2D
对象,你可以在图像上进行各种图形绘制、颜色填充、文本渲染等操作。
总的来说,这两行代码创建了一个指定大小的空白图像,并获取了一个可以对该图像进行绘制和操作的Graphics2D
对象。
QRCodeWriter qrCodeWriter = new QRCodeWriter(); BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
这两行代码是使用ZXing库(一个开源的条形码和二维码生成工具)来生成QR码的代码。
第一行代码创建了一个QRCodeWriter
对象,它是ZXing库中用于生成QR码的类。通过实例化QRCodeWriter
对象,我们可以使用其提供的方法来生成QR码。
第二行代码使用qrCodeWriter
对象的encode()
方法来生成QR码的位矩阵(BitMatrix
对象)。该方法接受五个参数:content
、BarcodeFormat.QR_CODE
、width
、height
和hints
。
content
是要编码为QR码的内容,通常是一个字符串。BarcodeFormat.QR_CODE
指定生成的条码类型为QR码。width
和height
指定QR码的宽度和高度(以像素为单位)。hints
是一个可选的参数,可以用来设置QR码生成的一些附加选项,例如纠错级别、编码字符集等。
qrCodeWriter.encode()
方法将根据提供的参数生成QR码的位矩阵,并将其赋值给bitMatrix
变量。
总体上,这两行代码使用ZXing库创建了一个QRCodeWriter对象,并使用该对象生成QR码的位矩阵。后续可以通过处理bitMatrix
对象来输出显示QR码或进行其他操作。
for (int xi = 0; xi < width; xi++) {
for (int yi = 0; yi < height; yi++) {
if (xi < x || xi > (x + metrics.stringWidth(text)) || yi < (y - metrics.getHeight()) || yi > y) {
if (bitMatrix.get(xi, yi)) {
image.setRGB(xi, yi, Color.BLACK.getRGB()); }
else { image.setRGB(xi, yi, Color.WHITE.getRGB()); } } } }
这段代码是用于将生成的 QR 码位矩阵绘制到图像上的代码。
外层循环 for (int xi = 0; xi < width; xi++)
遍历图像的宽度,内层循环 for (int yi = 0; yi < height; yi++)
遍历图像的高度。
接下来是一个条件判断语句 if
,判断当前坐标 (xi, yi)
是否在要绘制 QR 码的范围之外。判断的条件如下:
xi < x
:坐标xi
小于起始绘制点的横坐标x
。xi > (x + metrics.stringWidth(text))
:坐标xi
大于起始绘制点的横坐标加上文本的宽度。yi < (y - metrics.getHeight())
:坐标yi
小于起始绘制点的纵坐标减去文本的高度。yi > y
:坐标yi
大于起始绘制点的纵坐标。
如果以上条件都满足,则进入内部的 if
分支。在内部的 if
分支中,首先通过 bitMatrix.get(xi, yi)
方法判断 QR 码位矩阵中的对应位置是否为黑色(即为 true),如果是,则使用 image.setRGB(xi, yi, Color.BLACK.getRGB())
将图像的对应位置设置为黑色。否则,将图像的对应位置设置为白色,即 image.setRGB(xi, yi, Color.WHITE.getRGB())
。
通过这段代码,可以将生成的 QR 码位矩阵绘制到图像上,并根据条件判断来决定绘制位置的颜色。未满足条件的位置将被设为白色,满足条件的位置将被设为黑色,最终生成一个带有 QR 码的图像。