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

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

前言

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

yml 复制代码
wk.image.storage=d:/eldhealth-work/data/wk-images
wk.image.max_storage_size=524288000

WkConfig

java 复制代码
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

java 复制代码
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

java 复制代码
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

下载插件

shell 复制代码
npm install --save html2canvas

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

share.html

测试页面

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

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);

	
});
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>
    <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

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

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

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

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

相关推荐
codeniu4 分钟前
@logicflow/vue-node-registry 在 Vite 中无法解析的踩坑记录与解决方案
前端·javascript
孟祥_成都11 分钟前
AI 术语满天飞?90% 的人只懂名词,不懂为什么!
前端·人工智能
Lupino38 分钟前
被 React “玩弄”的 24 小时:为了修一个不存在的 Bug,我给大模型送了顿火锅钱
前端·react.js
米丘44 分钟前
了解 Javascript 模块化,更好地掌握 Vite 、Webpack、Rollup 等打包工具
前端
Heo1 小时前
深入 React19 Diff 算法
前端·javascript·面试
滕青山1 小时前
个人所得税计算器 在线工具核心JS实现
前端·javascript·vue.js
小怪点点1 小时前
手写promise
前端·promise
国思RDIF框架1 小时前
RDIFramework.NET Web 敏捷开发框架 V6.3 发布 (.NET8+、Framework 双引擎)
前端
Mintopia1 小时前
如何在有限的时间里,活出几倍的人生
前端
炫饭第一名1 小时前
速通Canvas指北🦮——变形、渐变与阴影篇
前端·javascript·程序员