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

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

相关推荐
YBN娜8 分钟前
Vue实现登录功能
前端·javascript·vue.js
阳光开朗大男孩 = ̄ω ̄=8 分钟前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
minDuck12 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
小政爱学习!33 分钟前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
魏大帅。38 分钟前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax
花花鱼44 分钟前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui
k09331 小时前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
EricWang13581 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning1 小时前
React.lazy() 懒加载
前端·react.js·前端框架
web行路人1 小时前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架