使用wkhtmltoimage实现生成长图分享
需求
用户可以选择以长图的形式分享本网页
方法
- wkhtmltopdf
- wkhtmltopdf url file
- wkhtmltoimage url file
- java
- Runtime.getRuntime().exec()
下载
直接去官网下载对应的版本:官网
命令行使用WK
> wkhtmltopdf https://www.nowcoder.com /opt/project/java/mycommunity-pdfs/1.pdf
Loading pages (1/6)
Counting pages (2/6)
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Done> wkhtmltoimage https://www.nowcoder.com /opt/project/java/mycommunity-images/1.png
Loading page (1/2)
Rendering (2/2)
Done// 上面那条命令生成的长图太大了,可以使用下面这条:以75%的质量输出
> wkhtmltoimage --quality 75 https://www.nowcoder.com /opt/project/java/mycommunity-images/1.png
Loading page (1/2)
Rendering (2/2)
Done
在java中调用
application.properties:
mycommunity.path.domain=http://localhost:8080
server.servlet.context-path=/myCommunity
# WK
wk.image.command=/usr/local/bin/wkhtmltoimage
wk.image.storage=/opt/project/java/mycommunity-images/
WK配置类,在每次程序开始运行时自动生成存放图像的文件夹
@Configuration
public class WkConfig {private static final Logger logger = LoggerFactory.getLogger(WkConfig.class);@Value("${wk.image.storage}")private String wkImageStorage;@PostConstructpublic void init(){// create the dic about WKimageFile file = new File(wkImageStorage);if(!file.exists()){file.mkdir();logger.info("create the dictionary of WKimage: " + wkImageStorage);}}
}
调用WK的控制层,因为生成长图比较耗时,所以使用异步操作,在用户操作时调用Kafka的生产者生成事件,通知消费者:
@Controller
public class ShareController implements CommunityConstant {private static final Logger logger = LoggerFactory.getLogger(ShareController.class);@Autowiredprivate EventProducer eventProducer;@Value("${mycommunity.path.domain}")private String domain;@Value("${server.servlet.context-path}")private String contextPath;@Value("${wk.image.storage}")private String wkImageStorage;@GetMapping(path = "/share")@ResponseBodypublic String share(String htmlUrl){// generate the file nameString fileName = CommunityUtil.generateUUID();// Asynchronous generation long picEvent event = new Event().setTopic(TOPIC_SHARE).setData("htmlUrl", htmlUrl).setData("fileName", fileName).setData("suffix", ".png");eventProducer.fireEvent(event);Map<String, Object> map = new HashMap<>();map.put("shareUrl", domain + contextPath + "/share/image" + fileName);return CommunityUtil.getJSONString(0, null, map);}//@GetMapping(path = "/share/image/{fileName}")public void getShareImage(@PathVariable("fileName") String fileName, HttpServletResponse response){if(StringUtils.isBlank(fileName)){throw new IllegalStateException("the file name cannot be blank");}response.setContentType("image/png");File file = new File(wkImageStorage + "/" + fileName + ".png");try {OutputStream os = response.getOutputStream();FileInputStream fis = new FileInputStream(file);byte[] data = new byte[1024];int len = 0;while ((len = fis.read(data)) != -1) {os.write(data, 0, len);}} catch (IOException e) {logger.error("querty the long image failed: ", e.getMessage());}}
}
Kafka的消费者,定义如何消费生成长图的事件:
@Component
public class EventConsumer implements CommunityConstant {@Autowiredprivate static final Logger logger = LoggerFactory.getLogger(EventConsumer.class);@Value("${wk.image.storage}")private String wkImageStorage;@Value("${wk.image.command}")private String wkImageCommand;@KafkaListener(topics = {TOPIC_SHARE})public void handleShareMessage(ConsumerRecord record) {if (record == null || record.value() == null) {logger.error("the content of the message is empty");return;}Event event = JSONObject.parseObject(record.value().toString(), Event.class);if (event == null) {logger.error("message format error");return;}String htmlUrl = (String) event.getData().get("htmlUrl");String fileName = (String) event.getData().get("fileName");String suffix = (String) event.getData().get("suffix");String cmd = wkImageCommand + " --quality 75 " + htmlUrl + " " + wkImageStorage + "/" + fileName + suffix;try {Runtime.getRuntime().exec(cmd);logger.info("generate long image successfully: " + cmd);} catch (IOException e) {logger.info("generate long image fail: " + e.getMessage());}}
}
测试

相关文章:
使用wkhtmltoimage实现生成长图分享
需求 用户可以选择以长图的形式分享本网页 方法 wkhtmltopdf wkhtmltopdf url filewkhtmltoimage url file java Runtime.getRuntime().exec() 下载 直接去官网下载对应的版本:官网 命令行使用WK > wkhtmltopdf https://www.nowcoder.com /opt/project/…...
新风机未来什么样?
新风机在未来将会有许多令人期待的发展和改进,让我们一起来看一看吧!以下是新风机未来的一些可能性: 智能化和智能家居:新风机将更多地与智能家居系统整合,通过物联网和人工智能技术,实现智能控制和智能调节…...
python的几种数据类型的花样玩法(一)
Python是一种动态类型语言,这意味着在Python中,你可以操作多种不同的数据类型,而且这些数据类型可以自动转换。以下是一些Python数据类型的花样玩法: 数字: 整数 (1, 100, -786 等) 浮点数 (1.1, -78.4, 3.14159 等)…...
python回调函数之获取jenkins构建结果
前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 需求背景: 现在用jenkins构建自动化测试(2个job),公司现将自动化纳入到发布系统 要求每次构建成功之后&am…...
Docker底层实现
Docker采用c/s架构,Docker守护进程( Daemon )作为服务端,接受来自客户端(命令行)的请求,并处理这些请求(创建、运行、分发容器) 。客户端和服务端既可以运行在一个机器上…...
PY32F003F18之RS485通讯
PY32F003F18将USART2连接到RS485芯片,和其它RS485设备实现串口接收后再转发的功能。 一、测试电路 二、测试程序 #include "USART2.h" #include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf() #include "…...
概率论与数理统计学习笔记(7)——全概率公式与贝叶斯公式
目录 1. 背景2. 全概率公式3. 贝叶斯公式 1. 背景 下图是本文的背景内容,小B休闲时间有80%的概率玩手机游戏,有20%的概率玩电脑游戏。这两个游戏都有抽卡环节,其中手游抽到金卡的概率为5%,端游抽到金卡的概率为15%。已知小B这天抽…...
深入了解 Axios 的 put 请求:使用技巧与最佳实践
在前端开发中,我们经常需要与后端服务器进行数据交互。其中,PUT 请求是一种常用的方法,用于向服务器发送更新或修改数据的请求。通过发送 PUT 请求,我们可以更新服务器上的资源状态。 Axios 是一个流行的 JavaScript 库࿰…...
浅谈Http协议、TCP协议(转载)
TCP标志位,有6种标示:SYN(synchronous建立联机) ,ACK(acknowledgement 确认) ,PSH(push传送),FIN(finish结束) ,RST(reset重置), URG(urgent紧急) Sequence number(顺序号码) ,Acknowledge num…...
flatten-maven-plugin使用
这篇文章主要介绍了flatten-maven-plugin使用,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 − 目录 一、简介 1.1 作用1.2 goal介绍二、使用总结 一、简介 1.1 作用 将pom工程父子pom的版…...
Vue3中快速简单使用CKEditor 5富文本编辑器
Vue3简单使用CKEditor 5 前言准备定制基础配置富文本配置目录当前文章demo目录结构 快速使用demo 前言 CKEditor 5就是内嵌在网页中的一个富文本编辑器工具 CKEditor 5开发文档(英文):https://ckeditor.com/docs/ckeditor5/latest/index.htm…...
qt简易网络聊天室 数据库的练习
qt网络聊天室 服务器: 配置文件.pro QT core gui networkgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exac…...
Navicat连接mysql8.0:提示无法加载身份验证插件“caching_sha2_password”
Navicat连接mysql时,提示:Unable to load authentication plugin ‘caching_sha2_password‘. 原因:mysql 8.0 默认使用 caching_sha2_password 身份验证机制。 D:\MySQL8.0\install\bin>mysql -uroot -p123456789 #登录 mysql: [War…...
手写签名到背景上合为1张图
手写签名到背景上合为1张图 package.json中 "signature_pad": "3.0.0-beta.3"<template><div class"home"><canvas id"canvas" width"500" height"300"></canvas><button click"…...
华为认证系统学习大纲及课程
前言 任何学习过程都需要一个科学合理的学习路线,才能够有条不紊的完成我们的学习目标。华为认证网络工程师所需学习的内容纷繁复杂,难度较大,所以今天特别为大家整理了一个全面的华为认证网络工程师学习大纲及课程,帮大家理清思…...
某米ax3000路由器组网解析
我们使用某米k60手机与某米ax3000 wifi6路由器组网,来分析和学习网络速率与瓶颈限制。 某米 AX3000 路由器简介 某米 AX3000 路由器是一款支持 WiFi 6 的双频路由器,它的 MIMO 是 22,也就是两根天线。MIMO 是 Multiple Input Multiple Outpu…...
【leetcode 力扣刷题】数学题之除法:哈希表解决商的循环节➕快速乘求解商
两道和除法相关的力扣题目 166. 分数到小数29. 两数相除快速乘解法一:快速乘变种解法二: 二分查找 快速乘 166. 分数到小数 题目链接:166. 分数到小数 题目内容: 题目是要我们把一个分数变成一个小数,并以字符串的形…...
Union类型和集合的union()方法-set.union()
Union类型和集合的Union 方法 一、Union类型1.Union类型由来2.Union类型的语法3.Union类型的使用4.一些等价写法 二、Set.union()union() 语法示例代码 一、Union类型 1.Union类型由来 Python中的Union类型是 3.10版本引入的新功能之一。它是一种特殊的类型注释,用…...
简明SQL别名指南:掌握AS实现列名更名
在 SQL 查询中,使用 {原始字段名} as {别名} 的语法来为查询结果的列赋予更直观的名称,以提高查询结果的可读性和可理解性。 以下是用到的表。 用AS更名 例如,查询表1的name字段,并将其更名为"名字",同时查…...
基于量子密钥分发和区块链技术的新一代加密通信系统
量子通信与区块链构建下一代加密通信基础设施 量子技术和区块链技术是国家信息安全和国家数字化转型的重要组成部分,在国家战略中具有重要地位。“十四五”规划纲要将“加快数字发展建设数字中国”作为独立篇章,指出要进一步明确发展云计算、大数据、物联…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
