https://blog.csdn.net/jam_fanatic/article/details/82818857
失效二维码方案:
1.生成二维码并把值设置为中转地址(某随机字符串,如www.a.com/qr/1111)
2.在redis中放入key: 1111, value: 真实二维码跳转地址,expire: 你想要的过期时间
用户扫码后,进入中转地址,在redis中检查是否存在这个key,如果存在则redirect到value,不存在则跳转到统一的过期页面。
注:Barcode编码格式介绍:https://blog.csdn.net/liudongdong19/article/details/80147404
MIME 参考手册:https://www.w3school.com.cn/media/media_mimeref.asp 也可以参考tomcat下conf文件下的web.xml的配置
像素说明:https://blog.csdn.net/elimago/article/details/5391582
比如data:image/png;base64,中png对应的是
image/png
<mime-mapping>
<extension>png</extension>
<mime-type>image/png</mime-type>
</mime-mapping>
使用base64生成二维码:
maven依赖:
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>2.2</version>
</dependency>
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.haierubic.cloud.datatools.dto.TransferTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.HashMap;
import static com.google.zxing.client.j2se.MatrixToImageConfig.BLACK;
import static com.google.zxing.client.j2se.MatrixToImageConfig.WHITE;
public class QrCodeUtils {
private static final Logger logger = LoggerFactory.getLogger(QrCodeUtils.class);
/**
* 设置编码方式,默认是“ISO-8859-1”编码方式
* 错误修正容量
* L 1 水平 7%的字码可被修正
* M 0 水平 15%的字码可被修正
* Q 3 水平 25%的字码可被修正
* H 2 水平 30%的字码可被修正
*/
public static HashMap hints = new HashMap() {
{
put(EncodeHintType.CHARACTER_SET, "utf-8");
put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
put(EncodeHintType.MARGIN, 0);
}
};
public static String creatRrCode(String content, int width, int height, String imgType, String imgValue, String icon, TransferTypeEnum iconWay, boolean hasIcon) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
String binary = null;
/* *
* contents:条形码/二维码内容
* format:编码类型,如 条形码,二维码 等;BarcodeFormat.QR_CODE为二维条码编码格式
* width:码的宽度,单位为像素
* height:码的高度,单位为像素
* hints:码内容的编码类型
* BarcodeFormat:枚举该程序包已知的条形码格式,即创建何种码,如 1 维的条形码,2 维的二维码 等
* BitMatrix:位(比特)矩阵或叫2D矩阵,也就是需要的二维码*/
BitMatrix bitMatrix = new MultiFormatWriter().encode(
content, BarcodeFormat.QR_CODE, width, height, hints);
BufferedImage image = toBufferedImage(bitMatrix);
//二维码中添加图片
if (hasIcon) {
if (TransferTypeEnum.BASE64STRING == iconWay) {
BASE64Decoder decoder = new BASE64Decoder();
byte[] bytes1 = decoder.decodeBuffer(icon);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);
//生成带base64 icon的二维码 base64
insertImage(image, null, bais, true);
bais.close();
} else {
//生成带URL icon的二维码 base64
URL url = new URL(icon);
insertImage(image, url, null, false);
}
}
//转换成type格式的IO流
ImageIO.write(image, imgType, out);
byte[] bytes = out.toByteArray();
// 2、将字节数组转为二进制
BASE64Encoder encoder = new BASE64Encoder();
String binaryTemp = encoder.encodeBuffer(bytes).trim();
binary = binaryTemp.replaceAll("\n", "").replaceAll("\r", "");
//获取mime
return "data:" + imgValue + ";base64," + binary;
} catch (Exception e) {
logger.error("Failed to generate QR code!!! content:{} icon:{}", content, icon, e);
throw e;
} finally {
out.close();
}
}
/**
* icon传入方式为url
*
* @param source
* @param url
* @throws Exception
*/
public static void insertImage(BufferedImage source, URL url, ByteArrayInputStream bais, boolean isBase64) throws Exception {
try {
Image src = null;
if (isBase64) {
src = ImageIO.read(bais);
} else {
src = ImageIO.read(url);
}
int width = source.getWidth();
int height = source.getHeight();
// 插入icon
Graphics2D graph = source.createGraphics();
int x = width * 7 / 20;
int y = height * 7 / 20;
int iconWidth = width - 2 * x;
int iconHeigth = height - 2 * x;
graph.drawImage(src, x, y, iconWidth, iconHeigth, null);
graph.dispose();
} catch (Exception e) {
logger.error("insertImage error!!!", e);
throw e;
}
}
/**
* 不去除白边
* image流数据处理
* 0xFFFFFFFF 白色像素 ;0xFF000000 黑色像素
* 像素生成模式 RGB
*/
public static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
return image;
}
/**
* 去除白边
* 读取二维码区域重新生成一个BitMatrix
*/
public static BufferedImage deleteWhite(BitMatrix matrix) {
//排除0bit
int[] rec = matrix.getEnclosingRectangle();
int resWidth = rec[2] + 1;
int resHeight = rec[3] + 1;
BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
resMatrix.clear();
for (int i = 0; i < resWidth; i++) {
for (int j = 0; j < resHeight; j++) {
if (matrix.get(i + rec[0], j + rec[1])) {
resMatrix.set(i, j);
}
}
}
int width = resMatrix.getWidth();
int height = resMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, resMatrix.get(x, y) ? BLACK
: WHITE);
}
}
return image;
}
//图片转base64
public static String imageToBase64(String impagePath) throws Exception{
File file=new File(impagePath);
BufferedImage bufferedImage=null;
try {
//图片转base64
bufferedImage=ImageIO.read(file) ;
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
ImageIO.write(bufferedImage,"jpg",outputStream);
byte[] bytes=outputStream.toByteArray();
// 2、将字节数组转为二进制
BASE64Encoder encoder = new BASE64Encoder();
//BASE64Encoder.encodeBuffer 对字符串进行加密
String base64String = encoder.encodeBuffer(bytes).trim();
base64String.replaceAll("\n", "").replaceAll("\r", "");
System.out.println("data:image/jpeg;base64,"+base64String);
//return "data:image/jpeg;base64,"+base64String;
return base64String;
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
return null;
}
//base64转图片
public static void base64ToImage()throws Exception {
String base64String=imageToBase64("D://0/dog.jpg");
BASE64Decoder decoder=new BASE64Decoder();
byte[] bytes1 = decoder.decodeBuffer(base64String);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);
BufferedImage bi1 = ImageIO.read(bais);
File f1 = new File("d://out.jpg");
ImageIO.write(bi1, "jpg", f1);
}
}