网页转长图插件html2canvas【前端】

网页转长图插件html2canvas【前端】

  • 前言
  • 版权
  • 开源
  • 推荐
  • 网页转长图插件html2canvas【前端】
    • wkImageStorage
    • 流程
    • 使用
    • 后端
      • application.properties
      • WkConfig
      • ShareController
      • ImageCleanupTask
    • 前端
      • html2canvas.js
      • share.html
      • share.js
      • getShare.js
      • getShare.html
  • 最后

前言

2024-5-10 18:00:10

以下内容源自《【前端】》
仅供学习交流使用

版权

禁止其他平台发布时删除以下此话
本文首次发布于CSDN平台
作者是CSDN@日星月云
博客主页是https://jsss-1.blog.csdn.net
禁止其他平台发布时删除以上此话

开源

日星月云 / 测试html2canvas

jsss-1 / test-html2canvas

推荐

网页转长图插件html2canvas【前端】

wkImageStorage

wkhtmltoimage 不能导出动态数据
在这里插入图片描述

流程

要实现网页转长图的功能,可以使用以下步骤和技术:

  1. 前端部分:
  • 创建一个按钮或链接,触发网页转长图的操作。
  • 使用 HTML2Canvas 库将当前网页内容转换为 canvas 元素。
  • 将 canvas 元素转换为图片,并拼接成长图。
  1. 后端部分:
  • 前端通过 AJAX 将转换后的图片数据发送到后端。
  • 后端接收到图片数据后保存为图片文件。
  1. 完整步骤:
  • 用户点击网页上的按钮触发网页转长图的操作。
  • 前端使用 HTML2Canvas 将当前网页内容转换为 canvas 元素。
  • 前端将 canvas 元素转换为图片数据。
  • 前端通过 AJAX 将图片数据发送到后端。
  • 后端接收到图片数据后保存为图片文件。
  • 后端返回图片文件的 URL 给前端。
  • 前端显示长图或提供下载链接给用户。
  1. 注意事项:
  • 转换过程可能会涉及到跨域问题,需要确保前后端的跨域设置正确。
  • HTML2Canvas 库的使用需要注意性能,避免转换过程过慢或耗时过长。
  • 图片文件的存储位置和命名需要考虑安全性和可维护性。

以上是设计网页转长图功能的一般步骤,具体实现过程可能会根据项目需求和技术栈有所不同。希望这些信息对你有帮助,如果有任何问题或需要进一步的指导,请随时告诉我。

使用

html2canvas使用教程

html2canvas快速使用

后端

application.properties

wk.image.storage=d:/eldhealth-work/data/wk-images
wk.image.max_storage_size=524288000

WkConfig

package com.jsss.configuration;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;import javax.annotation.PostConstruct;
import java.io.File;@Configuration
public class WkConfig {private static final Logger logger = LoggerFactory.getLogger(WkConfig.class);@Value("${wk.image.storage}")private String wkImageStorage;@PostConstructpublic void init() {// 创建WK图片目录File file = new File(wkImageStorage);if (!file.exists()) {file.mkdir();logger.info("创建WK图片目录: " + wkImageStorage);}}}

ShareController

package com.jsss.share.controller;import com.jsss.common.BusinessException;
import com.jsss.common.ErrorCode;
import com.jsss.common.ResponseModel;
import com.jsss.common.Toolbox;
import com.jsss.utils.Constant;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletResponse;
import java.io.*;@Controller
@CrossOrigin(origins = "${jsss.web.path}", allowedHeaders = "*", allowCredentials = "true")
public class ShareController implements Constant, ErrorCode {private static final Logger logger = LoggerFactory.getLogger(ShareController.class);@Value("${jsss.web.path}")private String domain;@Value("${server.servlet.context-path}")private String contextPath;@Value("${wk.image.storage}")private String wkImageStorage;@PostMapping("/uploadImage")@ResponseBodypublic ResponseModel uploadImage(String token,String imageData) {// 截取 base64 编码的部分String base64Data = imageData.substring(imageData.indexOf(",") + 1);// 解码Base64字符串为字节数组byte[] imageBytes = Base64Utils.decodeFromString(base64Data);// 文件名String fileName = Toolbox.getRandomString();// 保存字节数组为图片文件String imagePath = wkImageStorage + "/" +  fileName+ ".png";try (FileOutputStream fos = new FileOutputStream(imagePath)) {fos.write(imageBytes);} catch (IOException e) {e.printStackTrace();return new ResponseModel("Error saving image");}return new ResponseModel(fileName);}// 获取长图@RequestMapping(path = "/share/image/{fileName}", method = RequestMethod.GET)@ResponseBodypublic void getShareImage(@PathVariable("fileName") String fileName, HttpServletResponse response) {if (StringUtils.isBlank(fileName)) {throw new BusinessException(PARAMETER_ERROR,"文件名不能为空!");}File file = new File(wkImageStorage + "/" + fileName + ".png");if (!file.exists()) {throw new BusinessException(PARAMETER_ERROR,"文件不存在!");}response.setContentType("image/png");try {OutputStream os = response.getOutputStream();FileInputStream fis = new FileInputStream(file);byte[] buffer = new byte[1024];int b = 0;while ((b = fis.read(buffer)) != -1) {os.write(buffer, 0, b);}} catch (IOException e) {logger.error("获取长图失败: " + e.getMessage());}}}

ImageCleanupTask

package com.jsss.share.component;import com.jsss.share.controller.ShareController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.Arrays;
import java.util.Date;@Component
public class ImageCleanupTask {private static final Logger logger = LoggerFactory.getLogger(ShareController.class);@Value("${wk.image.storage}")String DIRECTORY_PATH;@Value("${wk.image.max_storage_size}")long MAX_STORAGE_SIZE;@Scheduled(cron = "0 0 0 * * *") // 每天凌晨执行public void cleanupImages() {File directory = new File(DIRECTORY_PATH);if (!directory.exists()) {return; // 目录不存在,直接返回}long totalSize = 0;File[] files = directory.listFiles();if (files == null) {return; // 目录为空,直接返回}// 按文件最后修改时间从大到小排序Arrays.sort(files, (f1, f2) -> Long.compare(f2.lastModified(), f1.lastModified()));for (File file : files) {long fileSize = file.length();totalSize += fileSize;Date currentDate = new Date();Date fileDate = new Date(file.lastModified());boolean isBeforeToday = fileDate.before(currentDate);if (isBeforeToday || totalSize > MAX_STORAGE_SIZE) {file.delete();logger.info("删除图片: " + file.getName());}}}
}

前端

html2canvas.js

下载插件

npm install --save html2canvas

找到这个js,引入到项目中

share.html

测试页面

可以利用js把导出按钮添加到所有页面

$(document).ready(function() {// 创建要添加的<div>元素var content =<div class="nav navbar-nav navbar-right" id="share" style="padding; margin-right: 20px;"><button id="convertButton">导出</button></div>`;$(".container-fluid").append(content);});
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>老年人健康管理</title><link rel="icon" href="#"><link rel="stylesheet" href="./bootstrap/css/bootstrap.min.css"><link rel="stylesheet" href="./css/common.css"></head><body><nav class="navbar navbar-default"><div class="container-fluid"><div class="navbar-header"><a class="navbar-brand" href="#" target="_blank">老年人健康管理</a></div><div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"><ul class="nav navbar-nav"><li><a href="home.html">首页</a></li><li><a href="register.html">个人注册</a></li><li class="active"><a href="javascript:void(0);">账户登录 <span class="sr-only">(current)</span></a></li></ul></div></div></nav><div class="container"><button id="convertButton">导出</button></div></body><script src="./bootstrap/js/jquery-3.5.1.min.js"></script><script src="./bootstrap/js/bootstrap.min.js"></script><script src="./js/common.js"></script><script src="./js/user.js"></script><script src="./share/js/html2canvas.js"></script><script src="./share/js/share.js"></script></html>

share.js

// 绑定按钮点击事件
$(document).ready(function () {// 分享单击事件$("#convertButton").click(function (e) { share(e);});
});function share() {// 使用 HTML2Canvas 将当前网页内容转换为 canvas 元素html2canvas(document.documentElement).then(function(canvas) {// 将 canvas 转换为图片var imgData = canvas.toDataURL('image/png');$.ajax({type: 'POST',url: SERVER_PATH + "/uploadImage",data: {imageData: imgData},success: function(result) {var fileName = result.data;// 在新建标签页中打开 getShare 页面并传递文件名作为参数window.open('http://127.0.0.1:5500/getShare.html?fileName=' + fileName, '_blank');}});});
}

getShare.js

$(document).ready(function () {var fileName=$.getUrlParam("fileName");if(!fileName){false;}getShare(fileName);
});function getShare(fileName){var imageUrl = SERVER_PATH + "/share/image/"+fileName;console.log(imageUrl);// 显示长图var imgElement = document.createElement('img');imgElement.style.width = '100%';imgElement.style.height = '100%';imgElement.src = imageUrl;document.body.appendChild(imgElement);// 提供下载链接给用户// var downloadLink = document.createElement('a');// downloadLink.href = imageUrl;// downloadLink.download = 'image_file.jpg';// downloadLink.innerHTML = '下载图片';// document.body.appendChild(downloadLink);}

getShare.html

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>老年人健康管理</title><link rel="icon" href="#"><link rel="stylesheet" href="./bootstrap/css/bootstrap.min.css"><link rel="stylesheet" href="./css/common.css"></head><body></body><script src="./bootstrap/js/jquery-3.5.1.min.js"></script><script src="./bootstrap/js/bootstrap.min.js"></script><script src="./js/common.js"></script><script src="./js/user.js"></script><script src="./share/js/getShare.js"></script></html>

最后

2024-5-10 18:00:23

迎着日光月光星光,直面风霜雨霜雪霜。

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

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

相关文章

国内运营商选择爱立信,或因它的低频5G技术更先进,价格更便宜

国内某运营商将大笔5G设备订单交给爱立信&#xff0c;引发了掀然大波&#xff0c;影响仍在扩散&#xff0c;对此各方说什么原因都有&#xff0c;笔者认为爱立信此次斩获大单&#xff0c;可能在于它的低频5G设备更先进&#xff0c;价格更便宜&#xff0c;对于急于降低成本的国内…

2024高安全个人密码本程序源码,贴身密码管家-随机密码备忘录二代密码

项目概述&#xff1a; 在这个网络高度发展的时代&#xff0c;每个人都需要上网&#xff0c;而上网就不可避免地需要使用账号和密码。 在众多账号的情况下&#xff0c;你是否还在为复杂难记的密码感到烦恼&#xff1f;现在只需要记录一次&#xff0c; 就可以随时查看你的密码…

搭建一个vue3+vant4+vite4+pinia 的移动端h5模板

效果图 项目的创建和组件库的安装 项目创建 pnpm create vite vue3-vant4-vite-pinia-pro-h5注意&#xff1a; node版本控制在 18&#xff0c; 可以通过nvm来管理本地的node版本&#xff0c;具体可以看这篇文章 nvm的简单使用 vant-ui库的安装【这里安装的是 ^4.6.0 版本的】…

DDoS攻防,本质上是成本博弈!

在互联网里&#xff0c;分布式拒绝服务&#xff08;DDoS&#xff09;攻击作为一种常见的网络威胁&#xff0c;持续对网站、在线服务和企业基础设施构成严重挑战。本文旨在探讨实施DDoS攻击的大致成本、以及企业如何采取有效措施来防范此类攻击&#xff0c;确保业务连续性和网络…

LabVIEW的MEMS电容式压力传感器测试系统

LabVIEW的MEMS电容式压力传感器测试系统 针对传统微惯性测量单元(MIMU)标定方法存在的过程繁琐、标定周期长及设备复杂等问题&#xff0c;提出了一种基于LabVIEW软件的MIMU误差参数快速标定方法。通过软件上位机控制小型三轴转台&#xff0c;配合卡尔曼滤波器技术&#xff0c;…

成为一名算法工程师需要掌握哪些技术栈

成为算法工程师需要学习的编程技能主要包括以下几个方面&#xff1a; Python&#xff1a;Python是算法工程师最常使用的编程语言之一。它拥有简洁易读的语法和丰富的库&#xff0c;如NumPy、Pandas、SciPy、Matplotlib等&#xff0c;这些库为数据处理、科学计算和可视化提供了…

meshlab: pymeshlab保存物体的横截面(compute planar section)

一、关于环境 请参考&#xff1a;pymeshlab遍历文件夹中模型、缩放并导出指定格式-CSDN博客 二、关于代码 本文所给出代码仅为参考&#xff0c;禁止转载和引用&#xff0c;仅供个人学习。 本文所给出的例子是https://download.csdn.net/download/weixin_42605076/89233917中的…

[疑难杂症2024-004] 通过docker inspect解决celery多进程记录日志莫名报错的记录

本文由Markdown语法编辑器编辑完成&#xff0e; 写作时长: 2024.05.07 ~ 文章字数: 1868 1. 前言 最近我负责的一个服务&#xff0c;在医院的服务器上线一段时间后&#xff0c;利用docker logs查看容器的运行日志时&#xff0c;发现会有一个"莫名其妙"的报错&…

docker的centos容器使用yum报错

错误描述 学习docker过程中&#xff0c;基于 centos 镜像自定义新的镜像。拉取一个Centos镜像&#xff0c;并运行容器&#xff0c;容器安装vim&#xff0c;报错了。 报错&#xff1a;Error: Failed to download metadata for repo appstream: Cannot prepare internal mirror…

经典面试题---环形链表

1. 环形链表1. - 力扣&#xff08;LeetCode&#xff09; 要解决这道题&#xff0c;我们首先要挖掘出带环的链表与不带环的链表之间的差别。 以此&#xff0c;才能设计出算法来体现这种差别并判断。 二者最突出的不同&#xff0c;就是不带环的链表有尾结点&#xff0c;也就是说…

数据库数据恢复—SQL Server数据库ndf文件变为0KB的数据恢复案例

SQL Server数据库故障&#xff1a; 存储设备损坏导致存储中SQL Server数据库崩溃。对数据库文件进行恢复后&#xff0c;用户发现有4个ndf文件的大小变为0KB。该SQL Server数据库每10天生成一个大小相同的NDF文件&#xff0c;该SQL Server数据库包含两个LDF文件。 SQL Server数据…

头歌实践教学平台:CG1-v2.0-直线绘制

第4关&#xff1a;直线光栅化-任意斜率的Bresenham画线算法 一.任务描述 1.本关任务 (1)根据直线Bresenham算法补全line函数以绘制白色直线&#xff0c;其中直线斜率为任意情况。 (2)当直线方程恰好经过P(x,y)和T(x,y1)的中点M时&#xff0c;统一选取直线上方的T点为显示的像…

云效 Pipeline as Code 来了!这些场景,用好它效率翻倍!

从可视化编排到支持 YAML 编排 云效流水线 Flow 是开箱即用的企业级持续集成和持续交付工具&#xff0c;支持丰富的代码源、构建、自动化测试工具、多种部署类型和部署方式&#xff0c;与阿里云深度集成&#xff0c;还提供多种企业级特性&#xff0c;助力企业高效完成从开发到…

PTP 对时协议 IEEE1588 网络对时 计算原理

前言 本文将阐述 PTP 对时协议的原理&#xff0c;slave 节点如何根据获取的时间来纠正和更新自己的时间。 协议概述 整个通讯过程中会发送 4 种类型的数据包&#xff0c;用来支撑对时。下面是 4 个包的解释 Sync message: 由 master 发送&#xff0c;发起对时事务, slave 接…

《ElementUI 基础知识》el-tree 之“我的电脑”目录结构效果

前言 项目需求&#xff0c;Web 端获取服务器文件夹目录结构。目录数据是调接口获取&#xff0c;本篇略过&#xff0c;直接展现数据&#xff01; 效果 实现 html 代码 8 - 15 行&#xff0c;自定义节点信息&#xff1b;代码 9 - 14 行&#xff0c;判断 icon 显示&#xff1b…

通过物联网管理多台MQTT设备-基于米尔T527开发板

本篇测评由电子工程世界的优秀测评者“JerryZhen”提供。 本文将介绍基于米尔电子MYD-LT527开发板的网关方案测试。 一、系统概述 基于米尔-全志 T527设计一个简易的物联网网关&#xff0c;该网关能够管理多台MQTT设备&#xff0c;通过MQTT协议对设备进行读写操作&#xff0c;…

前端框架-echarts

Echarts 项目中要使用到echarts框架&#xff0c;从零开始在csdn上记笔记。 这是一个基础的代码&#xff0c;小白入门看一下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" co…

x6.js bug记录-流程图json数据导入进来之后拖拽节点,节点直接飞走了

添加josn数据进来之后虽然能正常渲染&#xff0c;但是只要一拖拽&#xff0c;则节点就直接飞走了&#xff0c;看不到了。 找了一下午的问题&#xff0c;最后发现。保存的json坐标位置是字符串类型&#xff0c;而这边的位置必须是数字类型。如下&#xff1a; {position: { x: &…

关于vs2019 c++ STL 中容器的迭代器的 -> 运算符的使用,以 list 双向链表为例

&#xff08;1&#xff09;如下的结构体 A &#xff0c;若有指针 p new A() &#xff1b;则可以使用 p->m &#xff0c; p->n 解引用运算符。 struct A { int m ; int n; } 对于 STL 中提供的迭代器&#xff0c;提供了类似于指针的功能。对迭代器也可以使用 -> 运算…

RS3236-ADJ8YF5功能和参数介绍及PDF资料

RS3236-ADJ8YF5功能和参数介绍及PDF资料-公司新闻-配芯易-深圳市亚泰盈科电子有限公司 品牌: RUNIC(润石) 封装: SOT-23-5 描述: 输出电压可调(参考电压0.81V),Iout500mA(Max),Vin7.5V(Max),带过温保护 输出类型: 可调 最大输入电压: 7.5V 输出电压: 810mV~6.6V 最大输出电流…