本文代码已放置 github:Mr-Write/SpringbootDemo: 各种demo案例 (github.com)
ZXing(Zebra Crossing)是一个开源的条码扫描和生成库,用于读取和生成各种类型的条码和二维码。它由 Google 开发并发布,目前由一群开源社区维护。
ZXing 支持多种常见的条码格式,包括一维条码(如EAN-13、Code 39、Code 128等)和二维码(如QR码、Data Matrix等)。它提供了各种编程接口和工具,可轻松地将条码扫描和生成功能集成到各种应用程序中。
主要特点包括:
ZXing 被广泛应用于各种领域,包括商业应用、物流管理、移动支付、票务系统等,它提供了方便易用的条码扫描和生成功能,为开发人员提供了一种简单而强大的工具来处理条码相关的需求。
<dependency>
<groupId>com.google.zxinggroupId>
<artifactId>javaseartifactId>
<version>3.1.0version>
dependency>
<dependency>
<groupId>commons-langgroupId>
<artifactId>commons-langartifactId>
<version>2.6version>
dependency>
EncodeHintType 是用来设置二维码编码时的一些额外参数的枚举类型,常用枚举值如下:
ERROR_CORRECTION
:
CHARACTER_SET
:
MARGIN
:
MultiFormatWriter 是一个便捷的二维码生成类,可以根据传入的 BarcodeFormat 参数,生成对应类型的二维码。
MultiFormatWriter 封装了一系列的二维码生成方法,可以生成多种格式的二维码,包括 QR Code、Aztec Code、PDF417、Data Matrix 等。
BarcodeFormat 是枚举类,通过它来制定二维码格式:
BitMatrix 是 ZXing 库中表示二维码矩阵的数据结构,它是由 0 和 1 构成的二维数组,用于存储二维码的编码信息。在二维码生成过程中,我们通过对BitMatrix 对象的构建和操作,最终生成一个可被扫描解码的二维码图像。
BitMatrix 实际上是一个 紧凑型的布尔型二维数组,往往只需要占用一个字节即可表示 8 位二进制。在使用 BitMatrix 时,我们可以通过其不同的方法,例如get()、set() 等,来获取、设置矩阵中每个位置的值。
在 ZXing 中,BitMatrix 常用于将编码后的信息转化为矩阵形式,并进行图像的生成和输出。在使用 ZXing 生成二维码时,我们首先需要使用MultiFormatWriter.encode() 方法来生成一个 BitMatrix;然后,在对 BitMatrix 进行各种处理和操作后,就可以在 UI 中显示和输出二维码。
总的来说,BitMatrix 是 ZXing 库中非常重要的数据结构之一,它负责存储和处理生成二维码图像所需的二进制信息,是实现二维码生成功能的关键。
BitMatrix 常用 API:
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>3.1.2version>
<relativePath/>
parent>
<properties>
<maven.compiler.source>17maven.compiler.source>
<maven.compiler.target>17maven.compiler.target>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.google.zxinggroupId>
<artifactId>javaseartifactId>
<version>3.1.0version>
dependency>
<dependency>
<groupId>commons-langgroupId>
<artifactId>commons-langartifactId>
<version>2.6version>
dependency>
dependencies>
下载地址:https://unpkg.com/axios/dist/axios.min.js
将页面内容另存为 axios.js 文件,保存到 resources/static/js 下即可。
在 resources/static/html/zxing 下新建 CommonBlackWhite.html:
doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成普通黑白二维码title>
head>
<body>
<input type="text" id="myContent">
<button id="myBtn">生成二维码button>
<hr>
<img id="myImg">
<script src="/js/axios.js">script>
<script>
const myContent = document.querySelector("#myContent");
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '') {
return
}
axios.get(`http://127.0.0.1:8080/zxing/getCommonBlackWhite?content=${myContent.value.trim()}`).then(response => {
// data 就是后端传给前端的数据
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 当请求出现错误时的回调函数
console.log(error);
})
})
script>
body>
html>
/**
* @author 狐狸半面添
* @create 2023-08-28 21:35
*/
public class ZXingUtils {
public static String generateBlackWhiteCode(String content) throws WriterException, IOException {
// 使用 Google 提供的 zxing 开源库,生成普通的黑白二维码
// 需要创建一个 Map 集合,使用这个 Map 集合存储二维码相关的属性(参数)
Map<EncodeHintType, Object> map = new HashMap<>(3);
// 设置二维码的误差校正级别
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 设置二维码的字符集
map.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 设置二维码四周的留白,单位为 px
map.put(EncodeHintType.MARGIN, 1);
// 创建 zxing 的核心对象,MultiFormatWriter(多格式写入器)
// 通过 MultiFormatWriter 对象来生成二维码
MultiFormatWriter writer = new MultiFormatWriter();
// writer.encode(内容, 什么格式的二维码, 二维码宽度, 二维码高度, 二维码参数)
// 位矩阵对象(位矩阵对象内部实际上是一个二维数组,二维数组中每一个元素是 boolean 类型,true 代表黑色,false 代表白色)
BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, 300, 300, map);
// 获取矩阵的宽度
int width = bitMatrix.getWidth();
// 获取矩阵的高度
int height = bitMatrix.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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
FastByteArrayOutputStream fos = new FastByteArrayOutputStream();
ImageIO.write(image, "png", fos);
// 获取二维码图片的 base64 编码
String imgEncode = Base64.encodeBase64String(fos.toByteArray());
fos.flush();
// 返回 base64 编码
return imgEncode;
}
}
/**
* @author 狐狸半面添
* @create 2023-08-28 21:35
*/
@CrossOrigin // 允许跨域
@RestController
@RequestMapping("/zxing")
public class ZXingController {
@GetMapping("/getCommonBlackWhite")
public Map<String, String> getCommonBlackWhite(@RequestParam("content") String content) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", ZXingUtils.generateBlackWhiteCode(content));
return map;
}
}
启动 SpringBoot 应用,访问静态页面:http://localhost:8080/html/zxing/CommonBlackWhite.html
在 1.4 节代码基础上进行补充即可。
在 resources/static/html/zxing 下新建 ZXingLogo.html:
<%@page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
doctype html>
<html>
<head>
<title>生成带有logo的黑白二维码title>
<meta charset="UTF-8">
head>
<body>
<form action="/myqrcode/generateWithLogo" method="post" enctype="multipart/form-data">
请输入文本内容:<input type="text" name="url"><br>
请选择图片:<input type="file" name="logo"><br>
<input type="submit" value="生成带有logo的二维码"/>
form>
body>
html>
public static String generateLogoCode(String content, MultipartFile logo) throws WriterException, IOException {
// 使用 Google 提供的 zxing 开源库,生成普通的黑白二维码
// 需要创建一个 Map 集合,使用这个 Map 集合存储二维码相关的属性(参数)
Map<EncodeHintType, Object> map = new HashMap<>(3);
// 设置二维码的误差校正级别
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 设置二维码的字符集
map.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 设置二维码四周的留白,单位为 px
map.put(EncodeHintType.MARGIN, 1);
// 创建 zxing 的核心对象,MultiFormatWriter(多格式写入器)
// 通过 MultiFormatWriter 对象来生成二维码
MultiFormatWriter writer = new MultiFormatWriter();
// writer.encode(内容, 什么格式的二维码, 二维码宽度, 二维码高度, 二维码参数)
// 位矩阵对象(位矩阵对象内部实际上是一个二维数组,二维数组中每一个元素是 boolean 类型,true 代表黑色,false 代表白色)
BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, 300, 300, map);
// 获取矩阵的宽度
int width = bitMatrix.getWidth();
// 获取矩阵的高度
int height = bitMatrix.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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
// 给二维码添加 Logo
// 1.获取 logo 图片:通过 ImageIO 的read方法,从输入流中读取,从而获得 logo 图片
BufferedImage logoImage = ImageIO.read(logo.getInputStream());
// 2.设置 logo 的宽度和高度
int logoWidth = Math.min(logoImage.getWidth(), 60);
int logoHeight = Math.min(logoImage.getHeight(), 60);
// 3.将 logo 缩放:使用平滑缩放算法对原 logo 图像进行缩放得到一个全新的图像
Image scaledLogo = logoImage.getScaledInstance(logoWidth, logoHeight, Image.SCALE_SMOOTH);
// 4.将缩放后的 logo 画到黑白二维码上
// 4.1 获取一个 2D 的画笔
Graphics2D graphics2D = image.createGraphics();
// 4.2 指定开始的坐标 x,y
int x = (300 - logoWidth) / 2;
int y = (300 - logoHeight) / 2;
// 4.3 将缩放后的 logo 画上去
graphics2D.drawImage(scaledLogo,x,y,null);
// 4.4 创建一个具有指定位置、宽度、高度和圆角半径的圆角矩形,这个圆角矩形是用来绘制边框的
Shape shape = new RoundRectangle2D.Float(x,y,logoWidth,logoHeight,10,10);
// 4.5 使用一个宽度为 4px 的基本笔触
graphics2D.setStroke(new BasicStroke(4f));
// 4.6 给 logo 画圆角矩形
graphics2D.draw(shape);
// 4.7 释放画笔
graphics2D.dispose();
FastByteArrayOutputStream fos = new FastByteArrayOutputStream();
ImageIO.write(image, "png", fos);
// 获取二维码图片的 base64 编码
String imgEncode = Base64.encodeBase64String(fos.toByteArray());
fos.flush();
// 返回 base64 编码
return imgEncode;
}
@PostMapping("/getLogo")
public Map<String, String> getLogo(@RequestParam("content") String content, @RequestParam("logo") MultipartFile logo) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", ZXingUtils.generateLogoCode(content, logo));
return map;
}
启动 SpringBoot 应用,访问静态页面:http://localhost:8080/html/zxing/ZXingLogo.html
<dependency>
<groupId>com.github.liuyueyi.mediagroupId>
<artifactId>qrcode-pluginartifactId>
<version>3.0.0version>
dependency>
静态文件均在 resources/static/html/qrcodePlugin 下
http://localhost:8080/html/qrcodePlugin/CommonBlackWhiteCode.html
doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成普通黑白二维码title>
head>
<body>
<input type="text" id="myContent">
<button id="myBtn">生成普通黑白二维码button>
<hr>
<img id="myImg">
<script src="/js/axios.js">script>
<script>
const myContent = document.querySelector("#myContent");
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '') {
return
}
axios.get(`http://127.0.0.1:8080/qrcode-plugin/getCommonBlackWhiteCode?content=${myContent.value.trim()}`).then(response => {
// data 就是后端传给前端的数据
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 当请求出现错误时的回调函数
console.log(error);
})
})
script>
body>
html>
http://localhost:8080/html/qrcodePlugin/LogoBlackWhiteCode.html
doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成带 logo 的二维码title>
head>
<body>
请输入文本内容: <input type="text" name="content" id="myContent"><br>
请选择图片: <input type="file" name="logo" id="myLogo"><br>
<button id="myBtn" id="myBtn">生成带 logo 二维码button>
<hr>
<img id="myImg">
<script src="/js/axios.js">script>
<script>
const myContent = document.querySelector("#myContent");
const myLogo = document.querySelector("#myLogo")
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '' || myLogo.files.length === 0) {
return
}
axios.post('http://127.0.0.1:8080/qrcode-plugin/getLogoBlackWhiteCode', {
logo: myLogo.files[0],
content: myContent.value
}, {
headers: {
"Content-Type": "multipart/form-data",
},
}).then(response => {
// data 就是后端传给前端的数据
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 当请求出现错误时的回调函数
console.log(error);
})
})
script>
body>
html>
http://localhost:8080/html/qrcodePlugin/ColorCode.html
doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成彩色二维码title>
head>
<body>
<input type="text" id="myContent">
<button id="myBtn">生成彩色二维码button>
<hr>
<img id="myImg">
<script src="/js/axios.js">script>
<script>
const myContent = document.querySelector("#myContent");
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '') {
return
}
axios.get(`http://127.0.0.1:8080/qrcode-plugin/getColorCode?content=${myContent.value.trim()}`).then(response => {
// data 就是后端传给前端的数据
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 当请求出现错误时的回调函数
console.log(error);
})
})
script>
body>
html>
http://localhost:8080/html/qrcodePlugin/BgBlackWhiteCode.html
doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成带背景图的黑白二维码title>
head>
<body>
请输入文本内容: <input type="text" name="content" id="myContent"><br>
请选择图片: <input type="file" name="logo" id="myBgImg"><br>
<button id="myBtn" id="myBtn">生成带背景图的黑白二维码button>
<hr>
<img id="myImg">
<script src="/js/axios.js">script>
<script>
const myContent = document.querySelector("#myContent");
const myBgImg = document.querySelector("#myBgImg")
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '' || myBgImg.files.length === 0) {
return
}
axios.post('http://127.0.0.1:8080/qrcode-plugin/getBgBlackWhiteCode', {
backgroundImage: myBgImg.files[0],
content: myContent.value
}, {
headers: {
"Content-Type": "multipart/form-data",
},
}).then(response => {
// data 就是后端传给前端的数据
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 当请求出现错误时的回调函数
console.log(error);
})
})
script>
body>
html>
http://localhost:8080/html/qrcodePlugin/ShapeCode.html
doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成特殊形状的二维码title>
head>
<body>
<input type="text" id="myContent">
<button id="myBtn">生成特殊形状的二维码button>
<hr>
<img id="myImg">
<script src="/js/axios.js">script>
<script>
const myContent = document.querySelector("#myContent");
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '') {
return
}
axios.get(`http://127.0.0.1:8080/qrcode-plugin/getShapeCode?content=${myContent.value.trim()}`).then(response => {
// data 就是后端传给前端的数据
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 当请求出现错误时的回调函数
console.log(error);
})
})
script>
body>
html>
http://localhost:8080/html/qrcodePlugin/ImgFillCode.html
doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成图片填充二维码title>
head>
<body>
请输入文本内容: <input type="text" name="content" id="myContent"><br>
请选择图片: <input type="file" name="logo" id="myFillImg"><br>
<button id="myBtn" id="myBtn">生成图片填充二维码button>
<hr>
<img id="myImg">
<script src="/js/axios.js">script>
<script>
const myContent = document.querySelector("#myContent");
const myFillImg = document.querySelector("#myFillImg")
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '' || myFillImg.files.length === 0) {
return
}
axios.post('http://127.0.0.1:8080/qrcode-plugin/getImgFillCode', {
fillImg: myFillImg.files[0],
content: myContent.value
}, {
headers: {
"Content-Type": "multipart/form-data",
},
}).then(response => {
// data 就是后端传给前端的数据
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 当请求出现错误时的回调函数
console.log(error);
})
})
script>
body>
html>
/**
* @author 狐狸半面添
* @create 2023-08-29 21:41
*/
public class QrCodePluginUtils {
private static String imageParseBase64(BufferedImage image) throws IOException {
FastByteArrayOutputStream fos = new FastByteArrayOutputStream();
ImageIO.write(image, "png", fos);
// 获取二维码图片的 base64 编码
String imgEncode = Base64.encodeBase64String(fos.toByteArray());
fos.flush();
return imgEncode;
}
/**
* 生成普通黑白二维码
*
* @param content 文本内容
* @return 图片base64编码
*/
public static String generateBlackWhiteCode(String content) throws IOException, WriterException {
return imageParseBase64(QrCodeGenWrapper.of(content).asBufferedImage());
}
/**
* 生成带 logo 的黑白二维码
*
* @param content 文本内容
* @param logo logo文件
* @return 图片base64编码
*/
public static String generateLogoBlackWhiteCode(String content, MultipartFile logo) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
.setLogo(logo.getInputStream())
// 设置 logo 图片与二维码之间的比例,10 表示 logo 的宽度等于二维码的 1/10
.setLogoRate(10)
// 设置 logo 图片的样式,将 logo 的边框形状设置为圆形
.setLogoStyle(QrCodeOptions.LogoStyle.ROUND)
.asBufferedImage();
return imageParseBase64(image);
}
/**
* 生成彩色二维码
*
* @param content 文本内容
* @param color 颜色
* @return 图片base64编码
*/
public static String generateColorCode(String content, Color color) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
// 指定画笔颜色
.setDrawPreColor(color)
.asBufferedImage();
return imageParseBase64(image);
}
/**
* 生成带背景图片的黑白二维码
*
* @param content 文本内容
* @param backgroundImage 背景图文件
* @return 图片base64编码
*/
public static String generateBgBlackWhiteCode(String content, MultipartFile backgroundImage) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
// 设置背景图
.setBgImg(backgroundImage.getInputStream())
// 设置背景图透明度
.setBgOpacity(0.7F)
.asBufferedImage();
return imageParseBase64(image);
}
/**
* 生成带特殊形状的二维码
*
* @param content 文本内容
* @param drawStyle 绘制样式
* @return 图片base64编码
*/
public static String generateShapeCode(String content, QrCodeOptions.DrawStyle drawStyle) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
// 启用二维码绘制时的缩放功能
.setDrawEnableScale(true)
// 指定绘制样式
.setDrawStyle(drawStyle)
.asBufferedImage();
return imageParseBase64(image);
}
/**
* 生成图片填充二维码
*
* @param content 文本内容
* @param fillImg 填充图片
* @return 图片base64编码
*/
public static String generateImgFillCode(String content, MultipartFile fillImg) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
// 设置二维码的错误纠正级别
.setErrorCorrection(ErrorCorrectionLevel.H)
// 绘制二维码时采用图片填充
.setDrawStyle(QrCodeOptions.DrawStyle.IMAGE)
// 设置填充的图片
.addImg(1, 1, fillImg.getInputStream())
.asBufferedImage();
return imageParseBase64(image);
}
}
/**
* @author 狐狸半面添
* @create 2023-08-29 21:37
*/
@CrossOrigin
@RestController
@RequestMapping("/qrcode-plugin")
public class QrCodePluginController {
/**
* 生成普通黑白二维码
*
* @param content 文本内容
* @return 图片base64编码
*/
@GetMapping("/getCommonBlackWhiteCode")
public Map<String, String> getCommonBlackWhiteCode(@RequestParam("content") String content) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", QrCodePluginUtils.generateBlackWhiteCode(content));
return map;
}
/**
* 生成带 logo 的黑白二维码
*
* @param content 文本内容
* @param logo logo文件
* @return 图片base64编码
*/
@PostMapping("/getLogoBlackWhiteCode")
public Map<String, String> getLogoBlackWhiteCode(@RequestParam("content") String content, @RequestParam("logo") MultipartFile logo) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", QrCodePluginUtils.generateLogoBlackWhiteCode(content, logo));
return map;
}
/**
* 生成彩色二维码
*
* @param content 文本内容
* @return 图片base64编码
*/
@GetMapping("/getColorCode")
public Map<String, String> getColorCode(@RequestParam("content") String content) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
// 二维码颜色可以由前端传过来进行指定
map.put("imgEncode", QrCodePluginUtils.generateColorCode(content, Color.BLUE));
return map;
}
/**
* 生成带背景图片的黑白二维码
*
* @param content 文本内容
* @param backgroundImage 背景图文件
* @return 图片base64编码
*/
@PostMapping("/getBgBlackWhiteCode")
public Map<String, String> getBgBlackWhiteCode(@RequestParam("content") String content, @RequestParam("backgroundImage") MultipartFile backgroundImage) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", QrCodePluginUtils.generateBgBlackWhiteCode(content, backgroundImage));
return map;
}
/**
* 生成带特殊形状的二维码
*
* @param content 文本内容
* @return 图片base64编码
*/
@GetMapping("/getShapeCode")
public Map<String, String> getShapeCode(@RequestParam("content") String content) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
// 绘制样式可以由前端传过来进行指定,这里设定为 钻石
map.put("imgEncode", QrCodePluginUtils.generateShapeCode(content, QrCodeOptions.DrawStyle.DIAMOND));
return map;
}
/**
* 生成图片填充二维码
*
* @param content 文本内容
* @param fillImg 填充图片
* @return 图片base64编码
*/
@PostMapping("/getImgFillCode")
public Map<String, String> getImgFillCode(@RequestParam("content") String content, @RequestParam("fillImg") MultipartFile fillImg) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", QrCodePluginUtils.generateImgFillCode(content, fillImg));
return map;
}
}