生成二维码

main
zhangshengli 3 months ago
parent 749aa3a368
commit ab29031188

@ -0,0 +1,150 @@
package cn.iocoder.yudao.framework.common.util.qccode;
import cn.hutool.core.util.StrUtil;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.QRCodeWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.reader.ReaderException;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
/**
*
*
* Created by FSQ
* CopyRight https://www.huamar.com
*/
public class QRCodeUtil {
public static final Logger logger = LoggerFactory.getLogger(QRCodeUtil.class);
/**
*
*
* @param outputStream
* @param content
* @param width
* @param height
* @param imageFormat
* @param resource
*/
public static boolean createQrCode(OutputStream outputStream, String content, int width, int height, String imageFormat, String resource) {
//设置二维码纠错级别
HashMap<EncodeHintType, String> hints = new HashMap<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
/* width = width ;
height = height ;*/
try {
//创建比特矩阵(位矩阵)的QR码编码的字符串
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix byteMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
// 使BufferedImage勾画QRCode (matrixWidth 是行二维码像素点)
int matrixWidth = byteMatrix.getWidth();
BufferedImage image = new BufferedImage(matrixWidth - 200, matrixWidth - 200, BufferedImage.TYPE_INT_RGB);
// 使用比特矩阵画并保存图像
image.createGraphics();
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, matrixWidth, matrixWidth);
graphics.setColor(Color.BLACK);
for (int i = 0; i < matrixWidth; i++) {
for (int j = 0; j < matrixWidth; j++) {
if (byteMatrix.get(i, j)) {
graphics.fillRect(i - 100, j - 100, 1, 1);
}
}
}
if (StrUtil.isNotEmpty(resource)) {
BufferedImage big = getRemoteBufferedImage(resource);
BufferedImage small = image;
Graphics2D g = big.createGraphics();
// 二维码坐标(默认在右上角)
int x = big.getWidth() - small.getWidth() - 2;
int y = 2;
g.drawImage(small, x, y, small.getWidth(), small.getHeight(), null);
g.dispose();
return ImageIO.write(big, imageFormat, outputStream);
} else {
return ImageIO.write(image, imageFormat, outputStream);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return false;
}
/**
*
*/
public static void readQrCode(InputStream inputStream) throws IOException {
//设置二维码纠错级别
HashMap<DecodeHintType, String> hints = new HashMap<DecodeHintType, String>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
//从输入流中获取字符串信息
BufferedImage image = ImageIO.read(inputStream);
//将图像转换为二进制位图源
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
Result result = null;
try {
result = reader.decode(bitmap, hints);
} catch (ReaderException e) {
logger.error(e.getMessage(), e);
}
logger.info(result.getText());
}
/**
*
* @param imageURL
* @return
*/
public static BufferedImage getRemoteBufferedImage(String imageURL) {
URL url;
InputStream is = null;
BufferedImage bufferedImage = null;
try {
url = new URL(imageURL);
is = url.openStream();
bufferedImage = ImageIO.read(is);
} catch (MalformedURLException e) {
e.printStackTrace();
System.out.println("imageURL: " + imageURL + ",无效!");
return null;
} catch (IOException e) {
e.printStackTrace();
System.out.println("imageURL: " + imageURL + ",读取失败!");
return null;
} finally {
try {
if (is!=null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("imageURL: " + imageURL + ",流关闭异常!");
return null;
}
}
return bufferedImage;
}
}

@ -0,0 +1,32 @@
package cn.iocoder.yudao.framework.common.util.qccode.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "QRCodeConfig 二维码 vo")
@Data
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
public class QRCodeConfig {
// 二维码内容
@Schema(description = "二维码内容", requiredMode = Schema.RequiredMode.REQUIRED,defaultValue = "我是二维码的内容")
private String content;
// 二维码的宽度
@Schema(description = "二维码的宽度", requiredMode = Schema.RequiredMode.REQUIRED,defaultValue = "800")
private int width;
// 二维码的高度
@Schema(description = "二维码的高度", requiredMode = Schema.RequiredMode.REQUIRED,defaultValue = "800")
private int height;
// 二维码的图片格式,如"png", "jpg"等
@Schema(description = "二维码的高度", requiredMode = Schema.RequiredMode.REQUIRED,defaultValue = "png")
private String imageFormat;
// 附加资源或相关信息(具体含义根据项目需求定义)
/*private String resource;*/
}

@ -1,19 +1,27 @@
package cn.iocoder.yudao.module.infra.controller.app.file;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.UUID;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.qccode.QRCodeUtil;
import cn.iocoder.yudao.framework.common.util.qccode.vo.QRCodeConfig;
import cn.iocoder.yudao.module.infra.controller.app.file.vo.AppFileUploadReqVO;
import cn.iocoder.yudao.module.infra.service.file.FileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.*;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -35,4 +43,34 @@ public class AppFileController {
return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
}
@GetMapping("/qrCode")
@Operation(summary = "生成二维码")
public CommonResult<String> qrCode(@Valid QRCodeConfig qrCodeConfig) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
// 假设QRCodeUtil.createQrCode是一个正确实现的方法用于生成二维码并写入到ByteArrayOutputStream中
QRCodeUtil.createQrCode(out, qrCodeConfig.getContent(), qrCodeConfig.getWidth(), qrCodeConfig.getHeight(), qrCodeConfig.getImageFormat(), ""); // 使用PNG格式不是JPG
// 创建文件使用PNG扩展名因为QR码是以PNG格式生成的
File file = FileUtil.file(UUID.fastUUID()+"."+qrCodeConfig.getImageFormat()); // 注意文件扩展名应为.png
byte[] imageBytes = out.toByteArray();
// 使用 FileOutputStream 将字节数组写入本地文件
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(imageBytes);
}
// 输出文件名和位置
//System.out.println("文件名: " + file.getName());
//System.out.println("文件位置: " + file.getAbsolutePath());
// 假设fileService.createFile是一个正确实现的方法用于在您的服务中创建文件记录
// 读取文件内容并传递给createFile方法
byte[] fileContent = IoUtil.readBytes(new FileInputStream(file)); // 使用FileInputStream读取文件内容
String url = fileService.createFile(file.getName(), UUID.fastUUID()+"."+qrCodeConfig.getImageFormat(), fileContent);
out.close(); // 关闭ByteArrayOutputStream虽然在这个上下文中它会在方法结束时自动关闭
return success(url);
} catch (IOException e) {
e.printStackTrace(); // 适当的错误处理应该替换这一行,例如记录日志或向用户显示错误消息
}
return success("");
}
}

Loading…
Cancel
Save