用Java生成二维码并附带文字信息

网友投稿 355 2023-01-18

用Java生成二维码并附带文字信息

一、引入依赖

com.google.zxing

core

3.3.0

com.google.zxing

javase

3.3.0

二、生成二维码

2.1 创建实体类

代码如下:

@Data

public class QRCodeUser {

private String userName;

private String userCode;

private String url; //二维码跳转的链接

}

2.2 创建QRCodeUtil

代码如下:

import java.awt.*;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.OutputStream;

import java.util.*;

import java.util.List;

import javax.imageio.ImageIO;

import com.demo.demo.mapper.AssetsVo;

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 org.apache.commons.lang3.StringUtils;

public class QRCodeUtil {

//设置默认参数,可以根据需要进行修改

private static final int QRCOLOR = 0xFF000000; // 默认是黑色

private static final int BGWHITE = 0xFFFFFFFF; // 背景颜色

private static final int WIDTH = 180; // 二维码宽

private static final int HEIGHT = 180; // 二维码高

//设置高度常量

private static final int userNameHigh = 10;

private static final int userCodehigh = -20;

//设置字体宽度

private static final int strWidth = 130;

/**用于设置QR二维码参数

* com.google.zxing.EncodeHintType:编码提示类型,枚举类型

* EncodeHintType.CHARACTER_SET:设置字符编码类型

* EncodeHintType.ERROR_CORRECTION:设置误差校正

* ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction

* 不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的

* EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近

* */

private static Map hints = new HashMap() {

private static final long serialVersionUID = 1L;

{

put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置QR二维码的纠错级别(H为最高级别)具体级别信息

put(EncodeHintType.CHARACTER_SET, "utf-8");// 设置编码方式

put(EncodeHintType.MARGIN, 0);

}

};

/**

* 生成二维码和附带字体参数

*/

private static BufferedImage createQr(QRCodeUser qrCodeUser, Font font) throws WriterException{

//设置二维码旁边的文字信息

String userName = "员工姓名:"+qrCodeUser.getUserName();

String userCode = "員工工號:"+qrCodeUser.getUserName();

String qrurl = qrCodeUser.getUrl(); //这里以百度为例

/**

* MultiFormatWriter:多格式写入,这是一个工厂类,里面重载了两个 encode 方法,用于写入条形码或二维码

* encode(String contents,BarcodeFormat format,int width, int height,Map hints)

* contents:条形码/二维码内容

* format:编码类型,如 条形码,二维码 等

* width:码的宽度

* height:码的高度

* hints:码内容的编码类型

* BarcodeFormat:枚举该程序包已知的条形码格式,即创建何种码,如 1 维的条形码,2 维的二维码 等

* BitMatrix:位(比特)矩阵或叫2D矩阵,也就是需要的二维码

*/

MultiFormatWriter multiFormatWriter = new MultiFormatWriter();

/**参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数

* BitMatrix 的 get(int x, int y) 获取比特矩阵内容,指定位置有值,则返回true,将其设置为前景色,否则设置为背景色

* BufferedImage 的 setRGB(int x, int y, int rgb) 方法设置图像像素

* x:像素位置的横坐标,即列

* y:像素位置的纵坐标,即行

* rgb:像素的值,采用 16 进制,如 0xFFFFFF 白色

*/

BitMatrix bm = multiFormatWriter.encode(qrurl, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);

//创建一个图片缓冲区存放二维码图片

BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);

// 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色

for (int x = 0; x < WIDTH; x++) {

for (int y = 0; y < HEIGHT; y++) {

image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);

}

}

int height = image.getHeight();

// ------------------------------------------自定义文本描述-------------------------------------------------

if (StringUtils.isNotEmpty(qrCodeUser.getUserCode())) {

//在内存创建图片缓冲区 这里设置画板的宽高和类型

BufferedImage outImage = new BufferedImage(600, 350, BufferedImage.TYPE_4BYTE_ABGR);

//创建画布

GraphicIJXHsZYs2D outg = outImage.createGraphics();

// 在画布上画上二维码 X轴Y轴,宽度高度

outg.drawImage(image, 10, 30, image.getWidth(), image.getHeight(), null);

// 画文字到新的面板

outg.setColor(Color.BLACK);

// 字体、字型、字号

outg.setFont(font);

//获取字体宽度

int userNameWidth = outg.getFontMetrics().stringWidth(userName);

int userCodeWidth = outg.getFontMetrics().stringWidth(userCode);

//drawString(文字信息、x轴、y轴)方法根据参数设置文字的坐标轴 ,根据需要来进行调整

outg.drawString(userName, 300 - userNameWidth / 2, height - userNameHigh); // 员工名字

outg.drawString(userCode, 300 - userCodeWidth / 2, height - userCodehigh); // 员工工号

// 例: outg.drawString(depatmentName, 65 - strWidth / 2, height + (outImage.getHeight() - height) / 2 - h3); 根据需求自行计算需要的宽高

outg.dispose();

outImage.flush();

image = outImage;

}

image.flush();

return image;

}

}

此时二维码已经可以生成

2.3 生成单条二维码

/**

* @author: zyf

* @date: 2021/4/27

* Description: 生成单条二维码附带文字信息,导出到指定路径

**/

public void drawLogoQRCode(QRCodeUser qrCodeUser) {

FileOutputStream fileOutputStream = null;

try {

fileOutputStream = new FileOutputStream("D:"+ File.separator+"二维码" + qrCodeUser.getUserCode() + ".png"); //保存路径输出流,将图片输出到指定路径

Font fontChinese = new Font("黑体", Font.BOLD, 28);

BufferedImage image = QRCodeUtil.createQr(qrCodeUser,fontChinese);

boolean crateQRCode = ImageIO.write(image, "png", fileOutputStream);

}catch (WriterException | IOException e) {

log.error("二维码写入IO流异常",e);

}finally {

try {

if (null != fileOutputStream){

fileOutputStream.flush();

fileOutputStream.close();

}

}catch (IOException ioe){

log.error("二维码关流异常",ioe);

}

}

}

2.4 批量生产二维码

/**

* @author: zyf

* @date: 2021/4/27

* Description: 批量生产二维码,导出到指定路径

**/

public void drawLogoQRCode(List qrCodeUserList) {

FileOutputStream fileOutputStream = null;

//咱们简单一点,直接循环调用

try {

for(QRCodeUser qrCodeUser:qrCodeUserList){

fileOutputStream = new FileOutputStream("D:"+ File.separator+"二维码" + qrCodeUser.getUserCode() + ".png"); //保存路径输出流,将图片输出到指定路径

Font fontChinese = new Font("黑体", Font.BOLD, 28);

//返回的image就是二维码图片,可以根据需要进行后续的处理,比如全都写入指定文件夹进行压缩或者写入PDF文件

BufferedImage image = QRCodeUtil.createQr(qrCodeUser,fontChinese);

//写出到指定路径

boolean crateQRCode = ImageIO.write(image, "png", fileOutputStream);

}

}catch (WriterException | IOException e) {

log.error("二维码写入IO流异常",e);

}finally {

try {

if (null != fileOutputStream){

fileOutputStream.flush();

fileOutputStream.close();

}

}catch (IOException ioe){

log.error("二维码关流异常",ioe);

}

}

}

三、生成二维码写入PDF文件

3.1 引入依赖

com.itextpdf

itextpdf

5.5.13

com.itextpdf

itext-asian

5.2.0

3.2 替换工具类中的drawLogoQRCode方法

public static void drawLogoQRCode(OutputStream outputStream, QrCodeUser qrCodeUser) {

try {

Font fontChinese = new Font("黑体", Font.BOLD, 28);

BufferedImage image = createQr(qrCodeUser,fontChinese);

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); //字节数组输出流

boolean createQRCode = ImageIO.write(image, "png", byteArrayOutputStream);

if(!createQRCode){

log.error("二维码写入输出流失败");

}

/*生成pdf*/

Document document = new Document(PageSize.A4, 0, 0, 0, 0);

PdfWriter.getInstance(document, outputStream); //写出pdf

document.open(); //打开文件

/*pdf写入图片*/

com.lowagie.text.Image image2 = com.lowagie.text.Image.getInstance(byteArrayOutputStream.toByteArray());

float documentWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();

float documentHeight = documentWidth / 300 * 80;// 重新设置宽高

image2.scaleAbsolute(documentWidth, documentHeight);// 重新设置宽高

document.add(image2);

document.close(); //关闭文件

byteArrayOutputStream.close();

} catch (Exception e) {

e.printStackTrace();

}

}

3.3 PDF中文乱码解决

linux系统或者docker发布的项目中,不包含中文字体,会导致中文乱码,所以PDF中的中文不能显示

Linux系统中路径 /usr/share/fonts/ 下是字体文件,复制windows本地的字体文件到这里面就可以,一般使用宋体

Docker系统中,需要配置

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210428225743647.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjAxNDA3NQ==,size_16,color_FFFFFF,t_70)

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:springboot redis使用lettuce配置多数据源的实现
下一篇:音乐开放api接口(音乐网站api)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~