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

news2024/11/20 9:46:04

网页转长图插件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;

    @PostConstruct
    public 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")
    @ResponseBody
    public 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)
    @ResponseBody
    public 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.coloradmin.cn/o/1675206.html

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

相关文章

linux学习:多媒体开发库SDL+视频、音频、事件子系统+处理yuv视频源

目录 编译和移植 视频子系统 视频子系统产生图像的步骤 api 初始化 SDL 的相关子系统 使用指定的宽、高和色深来创建一个视窗 surface 使用 fmt 指定的格式创建一个像素点​编辑 将 dst 上的矩形 dstrect 填充为单色 color​编辑 将 src 快速叠加到 dst 上​编辑 更新…

SpringAMQP Work Queue 工作队列

消息模型: 代码模拟: 相较于之前的基础队列&#xff0c;该队列新增了消费者 不再是一个&#xff0c;所以我们通过代码模拟出两个consumer消费者。在原来的消费者类里写两个方法 其中消费者1效率高 消费者2效率低 RabbitListener(queues "simple.queue")public voi…

经典文献阅读之--U-BEV(基于高度感知的鸟瞰图分割和神经地图的重定位)

0. 简介 高效的重定位对于GPS信号不佳或基于传感器的定位失败的智能车辆至关重要。最近&#xff0c;Bird’s-Eye-View (BEV) 分割的进展使得能够准确地估计局部场景的外观&#xff0c;从而有利于车辆的重定位。然而&#xff0c;BEV方法的一个缺点是利用几何约束需要大量的计算…

React useEffect Hook: 理解和解决组件双重渲染问题

在React中&#xff0c;useEffect可能会在组件的每次渲染后运行&#xff0c;这取决于它的依赖项。如果你发现useEffect运行了两次&#xff0c;并且你正在使用React 18或更高版本的严格模式&#xff08;Strict Mode&#xff09;&#xff0c;这可能是因为在开发模式下&#xff0c;…

解锁楼宇自动化新维度西门子Insight+BACnet IP I/O控制器

数字城市的楼宇自动化已不再是一个遥不可及的概念&#xff0c;而是成为了现代建筑的标配。特别是在大型商业综合体、高端写字楼和公共设施中&#xff0c;高效的楼宇管理系统是确保环境舒适度与能源效率的关键。当提及楼宇自动化领域的佼佼者&#xff0c;西门子Insight楼宇自动化…

Spring WebFlux:响应式编程

在软件开发领域&#xff0c;随着互联网应用的规模和复杂性不断增加&#xff0c;传统的编程模型逐渐暴露出一些局限性&#xff0c;尤其是在面对高并发、大规模数据流处理等场景时。为了应对这些挑战&#xff0c;响应式编程&#xff08;Reactive Programming&#xff09;应运而生…

AuroraFOC使用指南一(STM32F405双路FOC)

一. 简介 哈喽&#xff0c;感谢各位选择AuroraFOC开发板&#xff0c;在这里将对其进行一个详细的介绍&#xff0c;方便大家使用。并且对提供的工程文件和上位机的操作也进行了详细的说明。 有什么疑问或者好的建议 可以微信联系: WU1356742146 最后再次感谢大家的支持。 Aur…

Transformers中加载预训练模型的过程剖析(一)

使用HuggingFace的Transformers库加载预训练模型来处理下游深度学习任务很是方便,然而加载预训练模型的方法多种多样且过程比较隐蔽,这在一定程度上会给人带来困惑。因此,本篇文章主要讲一下使用不同方法加载本地预训练模型的区别、加载预训练模型及其配置的过程,藉此做个记…

PostgreSQL 用户及授权管理 04:授予及回收权限

PostgreSQL 是一个坚如磐石的数据库&#xff0c;它非常注重安全性&#xff0c;提供了非常丰富的基础设施来处理权限、特权和安全策略。在前面的章节中以我们介绍的基本概念为基础&#xff0c;重新审视角色概念&#xff0c;特别关注授予角色的安全性和权限&#xff08;角色可以是…

Linux/ubuntu build编译make时出现has modification time int the future的问题解决方法

针对Linux由于双系统之间的时间冲突导致linux时间经常变化&#xff0c;出现执行make命令时出现“make[2]: Warning: File xxx.c’ has modification time 1.6e05 s in the future “警告的问题&#xff0c;亦或者虚拟机出现相同的问题。 由于时钟同步问题&#xff0c;出现 warn…

CAST: Cross-Attention in Space and Time for Video Action Recognition

标题&#xff1a;CAST: 时空交叉注意力网络用于视频动作识别 原文链接&#xff1a;2311.18825v1 (arxiv.org)https://arxiv.org/pdf/2311.18825v1 源码链接&#xff1a;GitHub - KHU-VLL/CASThttps://github.com/KHU-VLL/CAST 发表&#xff1a;NeurIPS-2023&#xff08;CCF A…

SwiftUI 调整视图内容周围间隙(Content Margins)的“时髦”方法

概述 在 SwiftUI 开发的应用中,往往在小屏设备(比如 iPhone)上布局良好的 App 放到大屏(iPad)上后就会“一塌糊涂”。因为它们一味的只想着“占据”却不知道“舍弃”。 从 iOS 17.0(iPad 17.0)开始苹果提供了原生的视图修改器方法专注于处理此事。 在本篇博文中,您将…

MVC WebAPI

创建项目 创建api控制器 》》》 web api 控制器要继承 ApiController 》》》 数据会自动装配 及自动绑定 》》》》FromBody&#xff1a; Post请求的基础类型的参数和Get请求有点不一样&#xff0c;我们知道Get请求的参数是通过Url来传递的&#xff0c;而Post请求则是通过H…

华为涅槃,余承东重生

最近一段时间&#xff0c;余承东甚为低调。最为明显的是&#xff0c;“遥遥领先”已经听不到了&#xff0c;“余大嘴”口中的措辞越来越克制。 今后手机相关的发布会&#xff0c;或许不再看到余承东的身影。 5月10日&#xff0c;余承东的职位正式更新&#xff0c;从终端BG CE…

暴雨分布式存储集群助重庆高校打造智慧校园

教育是国家发展的基石&#xff0c;教育兴则国家兴&#xff0c;教育强则国家强。党的二十大报告指出&#xff0c;“加快建设教育强国”&#xff0c;并提出到2035年“建成教育强国”的总体目标。随着数字时代的到来&#xff0c;以物联网、大数据、云计算和人工智能为代表的数字技…

Seal^_^【送书活动第4期】——《Web渗透测试技术》

Seal^_^【送书活动第4期】——《Web渗透测试技术》 一、参与方式二、本期推荐图书2.1 前 言2.2 关于本书2.3 本书读者2.4 图书简介2.5 作者荐语2.6 编辑推荐2.7 目 录 三、正版购买 掌握Web渗透测试技术&#xff0c;提高Web应用安全性。 一、参与方式 1、关注博主的账号。 2、点…

The Quantcast File System——论文泛读

VLDB 2013 Paper 分布式元数据论文阅读笔记整理 问题 在2013年之前&#xff0c;由于网络链路带宽有限&#xff0c;数据在集群中移动速度慢&#xff0c;因此Hadoop尽量将数据留在原来的位置&#xff0c;并将处理代码发送给它。随着网络链路的发展&#xff0c;可以之前更高的数…

【多人协作】场景模拟(一)

文章目录 实现多人协作场景&#xff1a;操作流程1开发人员a和b克隆仓库到本地2在本地仓库建立分支并与远程分支建立链接3开发人员工作并提交代码4将合并dev分支与master分支 实现多人协作 多人协作开发是git的最核心也是最重要的操作。多人协作也就意味着同一时间里&#xff0…

快速传输大文件:手机电脑互传文件的最佳解决方案

无论是工作还是生活&#xff0c;我们都可能需要将照片、视频、音乐或其他类型的文件从一台设备发送到另一台设备。然而&#xff0c;由于网络速度的限制&#xff0c;传统的文件传输方法可能会非常耗时。那么&#xff0c;有没有一种快速传输大文件的解决方案呢&#xff1f;答案是…

基于IDEA快速创建一个SpringMVC项目并且配置Tomcat

1&#xff0c;打开IDEA&#xff0c;新建Maven项目【使用web模板创建】 使用社区版的同学创建普通的maven项目&#xff0c;并配置项目的webapp&#xff0c;详情可参考 快速创建一个SpringMVC项目&#xff08;IDEA&#xff09; 2&#xff0c;在main目录下创建Java和resource目录…