二维码的生成、下载Java,并返回给前端展示

分析

将生成的二维码图片,以IO流的方式,通过response响应体直接返回给请求方。

第一、不需要落到我们的磁盘,操作在内存中完成,效率比较高。

第二、所有生成二维码的请求,都可以访问这里,前端直接拿img标签的src就能访问,你在浏览器直接输入这个路径也能得到一张图片,减少了很多交互和逻辑处理。

第三、在前端实现,因为前端可以将某个img标签的图片下载下来,不需要消耗我们的服务器资源。

一、引入依赖

<dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.0.0</version></dependency><dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.0.0</version></dependency>

二、编写工具类

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;public class QRCodeUtils {/***  生成二维码* @param content 二维码的内容* @return BitMatrix对象* */public static BitMatrix createCode(String content) throws IOException {//二维码的宽高int width = 200;int height = 200;//其他参数,如字符集编码Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");//容错级别为Hhints.put(EncodeHintType.ERROR_CORRECTION , ErrorCorrectionLevel.H);//白边的宽度,可取0~4hints.put(EncodeHintType.MARGIN , 0);BitMatrix bitMatrix = null;try {//生成矩阵,因为我的业务场景传来的是编码之后的URL,所以先解码bitMatrix = new MultiFormatWriter().encode(content,BarcodeFormat.QR_CODE, width, height, hints);//bitMatrix = deleteWhite(bitMatrix);} catch (WriterException e) {e.printStackTrace();}return bitMatrix;}/***  删除生成的二维码周围的白边,根据审美决定是否删除* @param matrix BitMatrix对象* @return BitMatrix对象* */private static BitMatrix deleteWhite(BitMatrix matrix) {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);}}return resMatrix;}
}

三、编写API接口

/***  生成二维码* @param type 二维码的类型,为了演示效果,1跳百度的,2是跳京东* */@GetMapping(value = "/activity/create/activity-code")@ApiOperation("生成活动详情二维码")public void getCode(int type , HttpServletResponse response) throws IOException {// 设置响应流信息response.setContentType("image/jpg");response.setHeader("Pragma", "no-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);OutputStream stream = response.getOutputStream();//type是1,生成活动详情、报名的二维码,type是2,生成活动签到的二维码String content = (type == 1 ? "http://www.baidu.com" : "http://www.jd.com");//获取一个二维码图片BitMatrix bitMatrix = QRCodeUtils.createCode(content);//以流的形式输出到前端MatrixToImageWriter.writeToStream(bitMatrix , "jpg" , stream);}

四、访问测试

注意添加type

这样的话二维码图片根本就不用落到服务器的磁盘,以流的方式就可以让前端直接访问。而且这个生成二维码的接口完全可以共用,因为它不保存二维码,只是返回图片的二进制流,你传入对应的参数我就生成不同的二维码,再返回对应的流。甚至二维码的目标链接你也可以让前端作为参数传给你(但是前端要进行URL Encode),减少了复杂性。

五、下载前端的代码

这一步,完全就是前端的工作

function downloadImage(imgsrc, name) {//下载图片地址和图片名let image = new Image();// 解决跨域 Canvas 污染问题image.setAttribute("crossOrigin", "anonymous");image.onload = function() {let canvas = document.createElement("canvas");canvas.width = image.width;canvas.height = image.height;let context = canvas.getContext("2d");context.drawImage(image, 0, 0, image.width, image.height);let url = canvas.toDataURL("image/jpg"); //得到图片的base64编码数据let a = document.createElement("a"); // 生成一个a元素let event = new MouseEvent("click"); // 创建一个单击事件a.download = name || "photo"; // 设置图片名称a.href = url; // 将生成的URL设置为a.href属性a.dispatchEvent(event); // 触发a的单击事件};image.src = imgsrc;}

imgSrc就是图片的地址,在这里指向我们上面的API就行,因为我们的API响应的就是一张图片嘛。name就是下载之后的文件名。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/794341.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习<四>JavaScript基础——04-标识符、关键字、保留字

变量的命名规则&#xff08;重要&#xff09; JS是大小敏感的语言。也就是说 A 和 a 是两个变量。大写字母是可以使用的&#xff0c;比如&#xff1a; var A 250; //变量1var a 888; //变量2 我们来整理一下变量的命名规则&#xff0c;非常重要。 必须遵守&#xff1a; 只…

使用阿里云试用Elasticsearch学习:1.3 基础入门——搜索-最基本的工具

现在&#xff0c;我们已经学会了如何使用 Elasticsearch 作为一个简单的 NoSQL 风格的分布式文档存储系统。我们可以将一个 JSON 文档扔到 Elasticsearch 里&#xff0c;然后根据 ID 检索。但 Elasticsearch 真正强大之处在于可以从无规律的数据中找出有意义的信息——从“大数…

Liunx进程信号

进程信号 进程信号什么是信号liunx信号种类 前后台进程前后台进程的概念 进程信号的产生键盘产生 阻塞信号信号的捕捉用户态和内核态 信号的捕捉函数 进程信号 什么是信号 信号是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知…

【leetcode面试经典150题】5.多数元素(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

【MySQL】:深入解析多表查询(上)

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; MySQL从入门到进阶 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. 多表关系1.1 一对多1.2 多对多1.3 一对一 二. 多表查询概述2.1 概述2.2 分类…

代码随想录Day45

Day 45 动态规划 part07 今日任务 爬楼梯 &#xff08;进阶&#xff09; 零钱兑换 279.完全平方数 代码实现 爬楼梯 &#xff08;进阶&#xff09; 完全背包应用&#xff0c;关键在于if判断 public static int climbStairs(int m, int n) {//如果每次可以爬m阶&#xff0c;…

基于Springboot的航班进出港管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的航班进出港管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

第十题:金币

题目描述 国王将金币作为工资&#xff0c;发放给忠诚的骑士。第一天&#xff0c;骑士收到一枚金币&#xff1b;之后两天&#xff08;第二天和第三天&#xff09;&#xff0c;每天收到两枚金币&#xff1b;之后三天&#xff08;第四、五、六天&#xff09;&#xff0c;每天收到…

中拔出溜的公司如何落地监控体系

又一项看似技术需求驱动&#xff0c;最终发现还是业务需求驱动的体系化建设。 0. 目录结构 1. 中拔出溜公司的特点2. 达成共识3. 推荐落地路线3.1 理论解析3.2 Loki Promtail Grafana 轻量级零侵入方案3.3 接入traceId3.4 基础设施监控 后记相关 1. 中拔出溜公司的特点 在传…

力扣---删除链表的倒数第 N 个结点

给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&#xff1a…

解决Word文档中插入MathTypeca公式编号问题(适用于本科、硕士、博士论文编写)

公式编号 这写论文过程中&#xff0c;我们常用到的就是根据章节号要求每写一个公式就自动编号&#xff0c;而不是(1)、&#xff08;2&#xff09;之类的。那么如下图这样的是怎么实现的呢&#xff1f; 1.开启Mathtype右编号 这样你才能有一个编号的格式 2.对公式进行格式化…

C++入门(以c为基础)——学习笔记2

1.引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空 间。在语法层面&#xff0c;我们认为它和它引用的变量共用同一块内存空间。 可以取多个别名&#xff0c;也可以给别名取别名。 b/c/d本质都是别名&#…

网络通信(二)

UDP服务器接收数据和发送数据 UDP协议时&#xff0c;不需要建立连接&#xff0c;只需要知道对方的IP地址和端口号&#xff0c;就可以直接发数据包。但是&#xff0c;能不能到达就不知道了。虽然用UDP传输数据不可靠&#xff0c;但它的优点是和TCP比&#xff0c;速度快&#xf…

C++的 stack和queue 的应用和实现【双端队列的理解和应用】

文章目录 stack的理解和应用栈的理解栈的模拟实现string实现stackvector实现stack queue的理解和应用队列的理解队列的模拟实现 双端队列原理的简单理解deque的缺陷为什么选择deque作为stack和queue的底层默认容器STL标准库中对于stack和queue的模拟实现stack的模拟实现queue的…

【LangChain学习之旅】—(19)CAMEL:通过角色扮演进行思考创作内容

【LangChain学习之旅】—(19)CAMEL:通过角色扮演进行思考创作内容 CAMEL 交流式代理框架股票交易场景设计场景和角色设置提示模板设计定义CAMELAgent类,用于管理与语言模型的交互预设角色和任务提示任务指定代理系统消息模板创建 Agent 实例头脑风暴开始总结大模型的成功,…

CSRF介绍及Python实现

CSRF 文章目录 CSRF1. CSRF是什么&#xff1f;2. CSRF可以做什么&#xff1f;3. CSRF漏洞现状4. CSRF的原理5. 举例说明6. CSRF的防御Python示例 1. CSRF是什么&#xff1f; CSRF&#xff08;Cross-Site Request Forgery&#xff09;&#xff0c;中文名称&#xff1a;跨站请求…

来get属于你的达坦科技令人心动的offer吧!

我们是谁 达坦科技始终致力于打造高性能Al Cloud 基础设施平台DatenLord&#xff0c;积极推动AI应用的落地。DatenLord通过软硬件深度融合的方式&#xff0c;提供高性能存储和高性能网络。为AI 应用提供弹性、便利、经济的基础设施服务&#xff0c;以此满足不同行业客户对AICl…

网络规划(homework 静态路由 and Rip路由表更新)

1、写出下图路由器1和路由器3中的路由表&#xff08;按直接交付、特定主机交付、特定网络交付、 默认交付的顺序放置路由项&#xff09; 2、写出Ri更新后的路由表&#xff08;rip路由协议&#xff09; 1、将Rj广播的路由消息全部1 2、直接对照着更新Ri中的路由表

SQLite字节码引擎(十二)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite的架构&#xff08;十一&#xff09;&#xff08;&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 1、 摘要 SQLite 的工作原理是将 SQL 语句转换为字节码和 然后在虚拟机中运行该字节码。本文档 …

关于地球内部猜想,火山和地震成因“之一”

地球内部是一个核反应堆&#xff0c;核反应堆向外释放能量。地面的火山和地震成因“之一”&#xff0c;太阳等能量可以通过辐射到达地球&#xff0c;南北极能量最强&#xff0c;因为磁场原因&#xff0c;地球上的四季是因为大气流动形成的&#xff0c;大气遵循涡流管的运动规律…