Vue+element-ui上传logo图片生成二维码展示到页面
该文章将介绍如何通过前端上传二维码logo图片在后台生成二维码,并将生成的二维码转换成Base64编码返回给前端在页面展示,用户扫码二维码跳转至指定页面,话不多说直接上代码!!!
1、添加Zxing的依赖(maven)
<!-- 生成二维码 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
2、添加生成二维码工具类
package com.kuang.mybatis_plus.util;
import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;
public class QRCodeUtil {
private static final String CHARSET = "utf-8";
private static final String FORMAT_NAME = "JPG";
// 二维码尺寸
private static final int QRCODE_SIZE = 300;
// LOGO宽度
private static final int WIDTH = 60;
// LOGO高度
private static final int HEIGHT = 60;
private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
hints);
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);
}
}
if (imgPath == null || "".equals(imgPath)) {
return image;
}
// 插入图片
QRCodeUtil.insertImage(image, imgPath, needCompress);
return image;
}
private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
File file = new File(imgPath);
if (!file.exists()) {
System.err.println("" + imgPath + " 该文件不存在!");
return;
}
Image src = ImageIO.read(new File(imgPath));
int width = src.getWidth(null);
int height = src.getHeight(null);
if (needCompress) { // 压缩LOGO
if (width > WIDTH) {
width = WIDTH;
}
if (height > HEIGHT) {
height = HEIGHT;
}
Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
src = image;
}
// 插入LOGO
Graphics2D graph = source.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
graph.drawImage(src, x, y, width, height, null);
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
}
public static void encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
mkdirs(destPath);
// String file = new Random().nextInt(99999999)+".jpg";
// ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file));
ImageIO.write(image, FORMAT_NAME, new File(destPath));
}
public static BufferedImage encode(String content, String imgPath, boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
return image;
}
public static void mkdirs(String destPath) {
File file = new File(destPath);
// 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
if (!file.exists() && !file.isDirectory()) {
file.mkdirs();
}
}
public static void encode(String content, String imgPath, String destPath) throws Exception {
QRCodeUtil.encode(content, imgPath, destPath, false);
}
// 被注释的方法
/*
* public static void encode(String content, String destPath, boolean
* needCompress) throws Exception { QRCodeUtil.encode(content, null, destPath,
* needCompress); }
*/
public static void encode(String content, String destPath) throws Exception {
QRCodeUtil.encode(content, null, destPath, false);
}
public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)
throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
ImageIO.write(image, FORMAT_NAME, output);
}
public static void encode(String content, OutputStream output) throws Exception {
QRCodeUtil.encode(content, null, output, false);
}
public static String decode(File file) throws Exception {
BufferedImage image;
image = ImageIO.read(file);
if (image == null) {
return null;
}
BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result;
Hashtable hints = new Hashtable();
hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
result = new MultiFormatReader().decode(bitmap, hints);
String resultStr = result.getText();
return resultStr;
}
public static String decode(String path) throws Exception {
return QRCodeUtil.decode(new File(path));
}
}
3、测试生成二维码
package com.kuang.mybatis_plus.test;
import com.kuang.mybatis_plus.util.QRCodeUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class testRedirect {
@Test
public void testRedirect() throws Exception {
String url= "https://www.baidu.com/"; // 存放在二维码中的内容,链接或者参数
String imgPath = "src/main/resources/imgs/reba.jpg"; //嵌入二维码的图片绝对路径也可以不放(logo图片)
String destPath = "src/main/resources/imgs/webapp1.jpg";// 生成的二维码存放的路径及名称
QRCodeUtil.encode(url, imgPath, destPath, true);//调用方法生成二维码
//获取二维码中存放的数据
String str = QRCodeUtil.decode(destPath);
System.out.println(str);
}
}
运行成功生成二维码
注意:我上面的图片都是放在resources目录下imgs文件夹中的
4、生成二维码接口的编写
package com.kuang.mybatis_plus.controller;
import com.kuang.mybatis_plus.util.QRCodeUtil;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping("/user")
@CrossOrigin
public class UploadController {
@RequestMapping("/upload")
public Object one(@RequestParam Map<String,String> map, @RequestParam("file") MultipartFile file) throws Exception {
String imgStr = "";
//使用uuid作为二维码图片名称
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String filename = file.getOriginalFilename();
//新建一个临时File对象,为了将MultipartFile对象转成File对象
File file1=new File("C:\\Users\\fei\\Desktop\\mybatis_plus\\src\\main\\resources\\imgs\\"+filename);
file.transferTo(file1);//将MultipartFile对象转成File对象
String url= "https://www.baidu.com/"; // 存放在二维码中的内容,链接或者参数
String imgPath = "src/main/resources/imgs/"+uuid+".jpg";//生成二维码图片的路径和名称
QRCodeUtil.encode(url,file1.toString(),imgPath, true);//生成二维码
//将生成的二维码图片转成File文件
File file11 = new File(imgPath);
System.out.println(file11.toString());
//将File文件转成Base64数据
FileInputStream fis = new FileInputStream(file11);
byte[] buffer = new byte[(int) file11.length()];
int offset = 0;
int numRead = 0;
while (offset < buffer.length && (numRead = fis.read(buffer, offset, buffer.length - offset)) >= 0) {
offset += numRead;
}
if (offset != buffer.length) {
throw new IOException("Could not completely read file "
+ file11.getName());
}
fis.close();
BASE64Encoder encoder = new BASE64Encoder();
imgStr = encoder.encode(buffer);
//删除临时文件
file11.delete();
file1.delete();
//返回Base64数据给前端
return "data:image/jpeg;base64,"+imgStr;
}
}
5、前端代码
前端使用的是Vue+element-ui,图片上传使用的是element-ui的上传组件 el-upload
注意:如果上传图片需要带上一些额外数据,放到 getfileData 中
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!-- 引入样式 -->
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<style>
.avatar {
width: 178px;
height: 178px;
display: block;
margin: auto;
}
</style>
</head>
<body>
<div id="app">
<el-upload
class="upload-demo"
drag
action="http://localhost:8080/user/upload"
:data="getfileData"
:on-success="handleAvatarSuccess"
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</div>
</body>
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
new Vue({
el: '#app',
data: function() {
return {
visible: false,
imageUrl:'',
dialogVisible: false,
getfileData:{
content:'1111'
}
}
},
methods: {
handleAvatarSuccess(res, file) {
console.log(res)
this.imageUrl=res
this.dialogVisible=true
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
}
}
})
</script>
</html>
6、展示页面
1、上传图片页面
2、点击上传图片,选择图片
3、上传成功,弹出二维码,扫码跳转百度