本工具类生成二维码图片直接上传本项目服务器,故需删减使用
添加maven依赖
com.google.zxing
core
3.1.0
com.google.zxing
javase
3.1.0
有详细注释,自行参考
/**
*
*/
package com.niuniu.core.util.zxingCode;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.UUID;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.niuniu.core.util.encrypt.BASE64;
import com.niuniu.core.util.excel.exception.ExcelException;
/**
* @Description:二维码生成工具类,上传服务器返回访问地址
* @author:tuizhi-cai
* @time:2018年2月2日 下午1:24:41
*/
public class QrcodeUtils {
private static final int BLACK = 0xFF000000;//颜色
private static final int WHITE = 0xFFFFFFFF; //背景色
private static final String FOMART = ".jpg";
private static final String yyyyMMddFormat = "yyyy-MM-dd";//用于当天时间格式创建dir目录
private static final Object OBJ = new Object();
/**
* @Author:tuzhi-cai
* @Description: 二维码构画
* @time:2018年2月2日下午2:03:26
*/
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) ? BLACK : WHITE));
}
}
return image;
}
/**
* @throws Exception
* @throws IOException
* @Author:tuzhi-cai(参数说明:用于匹配修改服务器时获取动态访问路径问题)
* @Param1 fielname :生成二维码文件名称
* @Param2 url :二维码参数地址
* @Param2.2 logUrl :中间log图片的路径 (可为null)
* @Param3 serverMapping:server服务器虚拟路径映射路径
* @param4 truePAth: 映射服务器的真实目录路径
* @Param4 serverIp: 服务器的域名地址
* @param5 request : 当前请求的request,用于获取端口号,
* @Param6 size : 二维码宽度和高度 (可为null)
* @Description:
* @time:2018年2月3日上午1:34:23
*/
public static String uploadAndCreateAndReuturnPath(String filename, String url, String logUrl ,String serverMappingPath,
String truePath, String serverIp, HttpServletRequest request,int[] size) throws IOException, Exception{
String serverPath = "http://"+serverIp+":"+request.getLocalPort()+serverMappingPath;//拼接服务器访问地址
SimpleDateFormat sdf=new SimpleDateFormat(yyyyMMddFormat); //将当天的日期作为新的文件夹
Date currDay = new Date();
String currentDate = sdf.format(currDay)+"/";
String savePath = truePath+currentDate;//拼接要保存的实际文件路径
String lastName = filename+FOMART;
File file = new File(savePath);
//判断当前日期文件夹是否存在不存在就创建
synchronized (OBJ) {
if (!file.exists()) {
file.mkdirs();
}
}
System.out.println(savePath+lastName+":最后的名路径");
System.out.println(serverPath+currentDate+lastName+"服务器访问路径");
//调用方法创建返回访问url
creatQrImage(url, savePath+lastName, logUrl,size);
return serverPath+currentDate+lastName;
}
/**
* 二维码参数设定
* @param content 二维码内url/内容
* @param outFileUri 二维码的生成地址
* @param logUri 二维码中间logo的地址
* @param size 用于设定图片大小(可变参数,宽,高)
*/
public static void creatQrImage(String content,String outFileUri,String logUri, int[] size) throws IOException, WriterException{
int width = 430; // 二维码图片宽度 430
int height = 430; // 二维码图片高度430
//如果存储大小的不为空,那么对我们图片的大小进行设定
/* if(size.length==2){
width=size[0];
height=size[1];
}else if(size.length==1){
width=height=size[0];
}*/
//二维码参数设置-- 纠错级别(L 7%、M 15%、Q 25%、H 30%)--字符集编码
Hashtable setMap = new Hashtable();
setMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
setMap.put(EncodeHintType.CHARACTER_SET, "utf-8");
setMap.put(EncodeHintType.MARGIN, 1);//设置二维码边的空度,非负数
//hints.put(EncodeHintType.MAX_SIZE, 350);// 图片的最大值
//hints.put(EncodeHintType.MIN_SIZE, 100);// 图片的最小值
//构造矩形--要编码的内容,编码类型,宽度,高度,生成条形码时的一些配置,此项可选
BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
BarcodeFormat.QR_CODE, //编码类型 :
width, // 宽度
height, // 高度
setMap);
// 构造要生成路径的file对象
File outputFile = new File(outFileUri); //System.out.println("输出文件路径为"+outputFile.getPath());
writeToFile(bitMatrix, outputFile,logUri);
}
/**
* @Author:tuzhi-cai
* @Description:生成二维码的方法,根据File对象
* @time:2018年2月2日下午2:00:19
*/
public static void writeToFile(BitMatrix matrix, File file,String logUri) throws IOException {
BufferedImage image = toBufferedImage(matrix);//new一个Image对象,对当前的矩阵对象进行绘画
//设置logo图标,返回带log的二维码,判断是否需要设置二维码的logo
if (logUri!=null&&logUri!="") {
image = setMatrixLogo(image, logUri);//设置logo图标,返回带log的二维码
}
Boolean isSuccess = ImageIO.write(image,"jpg", file);
if (!isSuccess){
throw new IOException("二维码生成失败");
}
}
/**
* @Author:tuzhi-cai
* @Description: 根据输出流对象
* @time:2018年2月2日下午2:14:09
*/
public static void writeToStream(BitMatrix matrix, OutputStream stream,String logUri) throws IOException {
BufferedImage image = toBufferedImage(matrix);
//设置logo图标,返回带log的二维码,判断是否需要设置二维码的logo
if (logUri!=null&&logUri!="") {
image = setMatrixLogo(image, logUri);
}
Boolean isSuccess = ImageIO.write(image, "jpg", stream);
if (isSuccess){
throw new IOException("二维码生成失败");
}
}
/**
* @Author:tuzhi-cai
* @Description: 传递二维码,设置带logo的二维码
* @time:2018年2月2日下午1:58:01
* @param matrixImage 生成的二维码
* @param logUri logo地址
* @return 带有logo的二维码
*/
public static BufferedImage setMatrixLogo(BufferedImage matrixImage,String logUri) throws IOException{
/**
* 读取二维码图片,并构建绘图对象
*/
Graphics2D g2 = matrixImage.createGraphics();
int matrixWidth = matrixImage.getWidth();
int matrixHeigh = matrixImage.getHeight();
BufferedImage logo = ImageIO.read(new File(logUri));//读取logo图片
//开始绘制图片前两个、/5*2/5*2 后/5
g2.drawImage(logo,matrixWidth/5*2,matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5, null);
//绘制边框
BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
// 设置笔画对象
g2.setStroke(stroke);
//指定弧度的圆角矩形
RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth/5*2, matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5,20,20);
g2.setColor(Color.white);
// 绘制圆弧矩形
g2.draw(round);
//设置logo 有一道灰色边框
BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
// 设置笔画对象
g2.setStroke(stroke2);
RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth/5*2+2, matrixHeigh/5*2+2, matrixWidth/5-4, matrixHeigh/5-4,20,20);
g2.setColor(new Color(128,128,128));
g2.draw(round2);// 绘制圆弧矩形
g2.dispose(); //执行刷出返回带logo二维码
matrixImage.flush() ;
return matrixImage ;
}
}
controller层
/**
* @Author:tuzhi-cai
* @time:2018年2月1日下午8:58:13
*/
@SuppressWarnings({ "rawtypes", "unused" })
@RequestMapping(value="/addChannel",method=RequestMethod.GET)
@ResponseBody
public Message add(String channelName,@RequestParam(value="skId",defaultValue="null")String skId,HttpServletRequest request){
try {
ShopKeeper shopKeeper = (ShopKeeper) SecurityUtils.getSubject().getPrincipal();
//生成唯一编号,生成带编号的认证链接link链接
String channelId = UUID.randomUUID().toString().replace("-", "");
//生成并上传二维码到服务器,返回访问路径
String codePictureUrl = QrcodeUtils.uploadAndCreateAndReuturnPath(channelId,url,null,
FILE_EXTERNA_MAPPING_ROOT_PATH,
FILE_ROOT_DIRECTORY,LOCAL_IP,request,null);
} catch (Exception e) {
e.printStackTrace();
return new Message<>(0, "添加失败,系统服务器在忙");
}
}