rrweb录制用户的操作过程,并上传服务端

news2025/1/12 3:58:26

1、客户端

准备工作,需要使用到的包有rrweb(录制) rrwebPlayer(播放) pako(压缩)

1.1、录制:1.2、pako 压缩工具的使用方式

import * as rrweb from 'rrweb'

let dispose = null
let rrwebEvents = []

console.log('开始录制 ========>>>>>>>>>>>>>>')
clearFile(); // 录制之前清楚本地缓存json文件
dispose = rrweb.record({
    emit(event) {
        rrwebEvents.push(event);
        // 以 rrwebEvents 的长度作为分片持续上传:
        if(rrwebEvents.length >= 50) {
            uploadFile();
            // 分片之后清空队列:    
            rrwebEvents = [];
        }
    }
})

console.log('结束录制 ========>>>>>>>>>>>>>>')
if (dispose) {
    // 实际场景需要分片传输的话,就不需要这个关闭,当真正业务不需要录制的时候再调用
    // 分片逻辑是,序列化的rrwebEvents.length的累加大于某个值  --- 分片逻辑看业务需求吧
    // 我们这里上传的时候是 gzip 后的文件上传,不是用的json方式,也需要后端解gzip,这里只负责演示前端,所以压缩逻辑就没写上
    // 压缩逻辑是 引入pako, 然后调用,就不体现了哈
    dispose()
}
if (rrwebEvents.length === 0) return
uploadFile();
rrwebEvents = []

 1.2、pako 压缩工具的使用方式

import pako from 'pako'

// 压缩
const data = "Hello, world!";  // 待压缩的数据
const compressedData = pako.deflate(data);  // 使用deflate方法进行压缩
console.log(compressedData);  // 输出压缩后的数据 Uint8Array(21) [120, 156, 243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 81, 4, 0, 32, 94, 4, 138]

// 解压
const decompressedData = pako.inflate(compressedData);  // 使用inflate方法进行解压缩
const unData = new TextDecoder().decode(decompressedData);
console.log(unData, '解压');  // 输出解压缩后的数据 Hello, world! 解压

1.3、调用接口

// 接口上传文件
function uploadFile() {
    console.log('上传文件 ========>>>>>>>>>>>>>>', '\n', rrwebEvents);
    fetch('http://localhost:8076/upload', {
        method: 'POST',
        headers: {
            'Content-type': 'application/json'
        },
        body: JSON.stringify({
            rrwebEvents
        })
    })
    .then(response => {
        console.log('response', response)
    })
    .catch(error => {
        console.log('error', error)
    })
}

// 清除文件
function clearFile() {
    fetch('http://localhost:8076/clearFile', {
        method: 'POST'
    })
    .then(response => {
        console.log('response', response)
    })
    .catch(error => {
        console.log('error', error)
    })
}

function getFile() {
    fetch('http://localhost:8076/getFile', {
        method: 'POST'
    }).then(response => response.json()).then(data => {
        new rrwebPlayer({
            target: document.getElementById('rrwebplayer'),
            data: {
                events: data.data,
                skipInactive: true,
                showDebug: true,
                showWarning: true,
                autoPlay: true
            }
        })
    })
}

2、服务端

使用node的Koa进行开发简易的服务端,使用文件存储的形式

const Koa = require('koa')
const router = require('koa-router')()
const cors = require('koa-cors')
const bodyParser = require('koa-bodyparser')
const fs = require('fs')
const path = require('path')
const app = new Koa()
app.use(cors())
app.use(bodyParser())

app.use(router.routes())
app.use(async (ctx, next) => {
    ctx.set('Access-Control-Allow-Origin', '*')
    ctx.set(
        'Access-Control-Allow-Headers',
        'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild'
    )
    ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS')
    if (ctx.method == 'OPTIONS') {
        ctx.body = 200
    } else {
        await next()
    }
})

router.post('/upload', ctx => {
    const jsonFile = path.join(process.cwd(), `./file/jsonFile${Date.now()}.json`)
    fs.writeFileSync(jsonFile, JSON.stringify(ctx.request.body.rrwebEvents))
    ctx.response.body = {
        status: '00'
    }
})

router.post('/getFile', ctx => {
    const fileDirPath = path.join(process.cwd(), `./file`);
    const files = fs.readdirSync(fileDirPath);
    let file;
    if(files && files.length) {
        file = fs.readFileSync(`${fileDirPath}/${files[0]}`);
    }
    ctx.response.body = {
        status: '00',
        data: JSON.parse(file)
    }
})

router.post('/clearFile', ctx => {
    const fileDirPath = path.join(process.cwd(), `./file`);
    const files = fs.readdirSync(fileDirPath);
    if(files && files.length) {
        files.forEach(item => {
            const filePath = `${fileDirPath}/${item}`;
            fs.unlinkSync(filePath);
        })
    }
    ctx.response.body = {
        status: '00'
    }
})

app.listen(8076)
console.log('listen on 8076')

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

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

相关文章

SSH项目集成DM达梦数据库

接上一篇文章【Mysql数据库迁移到达梦DM】,迁移完成后,做出的调整 目录 1.需要改成DM的连接数据的方式 2.启动项目报错 3.在做插入数据操作时报错 1.需要改成DM的连接数据的方式 jdbc.usernameJDYXKSBM jdbc.passwordJDYXKSBM jdbc.urljdbc:dm://lo…

五、高并发内存池--Thread Cache

五、高并发内存池–Thread Cache 5.1 Thread Cache的工作原理 thread cache是哈希桶结构,每个桶是一个按桶位置映射大小的内存块对象的自由链表。每个线程都会有一个thread cache对象,这样每个线程在这里获取对象和释放对象时都是无锁的。 每一个线程…

YOLOv5算法改进(11)— 替换主干网络之EfficientNetv2

前言:Hello大家好,我是小哥谈。EfficientNetV2是一个网络模型,旨在提供更小的模型和更快的训练速度。它是EfficientNetV1的改进版本。EfficientNetV2通过使用更小的模型参数和采用一种称为Progressive Learning的渐进学习策略来实现这一目标。…

Img标签的src地址自动拼接本地域名(localhost:8080)导致图片不显示问题

摘要:做Vueelement ui项目的时候,发现使用element ui的upload上传图片时,不显示的问题。我项目的图片是上传到七牛云,长传成功后返回存储在七牛云中的地址。后面发现是因为返回的地址是外部地址,需要完整的URL&#xf…

LVS 实现四层负载均衡项目实战--NAT模式

一、原理 就是把客户端发来的数据包的IP头的目的地址,在负载均衡器上换成其中一台RS的IP地址,转发至此RS来处理,RS处理完成后把数据交给经过负载均衡器,负载均衡器再把数据包的源IP地址改为自己的VIP,将目的地址改为客户端IP地址即可&#x…

【Linux系列】vmware虚拟机网络配置详解

非原创 原文地址[1] 首发博客地址[2] 系列文章地址[3] vmware 为我们提供了三种网络工作模式,它们分别是:Bridged(桥接模式)、NAT(网络地址转换模式)、Host-Only(仅主机模式)。 打开…

Linux:tomcat (源码包安装)(官网下载-安装-启动-配置-等等等-----从入门到入土)

介绍 Apache Tomcat软件是一个开源实现 Jakarta Servlet、Jakarta Server Pages、Jakarta Expression Language、Jakarta WebSocket、Jakarta Annotations 和 Jakarta Authentication 规范。 这些规范是Jakarta EE平台的一部分。 Apache Tomcat软件是在开放和参与式中开发的。 …

大数据时代下的数据安全防护

随着大数据时代的来临,数据安全防护成为了一个重要的问题。在大数据时代,数据的规模和价值都得到了极大的提升,因此数据安全的重要性也变得越来越突出。本文将从数据加密、访问控制、网络安全和人员管理四个方面来介绍大数据时代下的数据安全…

Ubuntu22.04上下左右全方位美化教程

Ubuntu22.04上下左右全方位美化教程 以Plank替代Dock甲板安装使用优化除了Plank之外还有Ubuntu-Launchpad可以替代Dock Tweak-Tool配置主题Theme的配置下载解压配置 Icon文件夹显示风格的配置Cursors鼠标风格优化Background背景、Lock锁屏以及登陆页面的更换过渡动画配置安装 E…

excel绘制直方图

Excel 2016直方图使用指南 excel绘制各种曲线十分方便,可以通过代码将计算的数据输出到excel里面,然后通过excel的插入标签,绘制各种需要的曲线。 对于直方图,横坐标是分布区间,纵坐标是这个区间内数值的频数&#x…

Nginx 部署 配置

一.概述 什么是nginx? Nginx (engine x) 是一款轻量级的Web 服务器 、反向代理服务器及电子邮件(IMAP/POP3)代理服务器。 什么是反向代理? 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求…

【vue2第七章】vue的四个生命周期与八个钩子函数

vue的四个生命周期与八个钩子函数 Vue的四个生命周期有:创建(creation)、挂载(mounting)、更新(updating)和销毁(destroying)。 钩子函数是什么: vue生命周…

React动态添加标签组件

背景 在前端开发的过程中,一些表单的输入经常需要输入多个内容,如果采用一个输入框逗号分隔的方式,展示起来不是很清晰,一般需要采用标签的方式 需求 可以指定空状态时的标题设置标签颜色每个标签的最大长度(字符数)接口传递的时候的分隔标记(是用逗号,还是其他)直接处理表单,不…

基于OpenCV+Keras+tensorflow 实现的变电站作业管控平台源代码。含人脸识别考勤,移动目标跟踪,越线检测,安全措施检测,姿态识别等功能

#综述 使用该作业现场安全生产智能管控平台来实现变电站的安全生产的智能化管理,通过人脸识别功能进行人员的考勤; 通过人员、车辆的检测和识别来实现变电站的智能化管理;通过安全行为识别和安全区域报警功能来实现对变电站内人员和设备安全的…

线程同步与互斥

目录 前言:基于多线程不安全并行抢票 一、线程互斥锁 mutex 1.1 加锁解锁处理多线程并发 1.2 如何看待锁 1.3 如何理解加锁解锁的本质 1.4 CRAII方格设计封装锁 前言:基于线程安全的不合理竞争资源 二、线程同步 1.1 线程同步处理抢票 1.2 如何…

分库分表相关知识

文章目录 一、为什么要分库分表1.1 什么是分库1.2 什么是分表1.3 为什么要分库1.3.1 磁盘存储1.3.2 并发连接支撑 1.4 为什么要分表 二、分库分表解决方案2.1 垂直(纵向)切分2.1.1 垂直切分优点2.1.2 垂直切分缺点 2.2 水平(横向)…

video 视频编解码一些debug方法

文章目录 一、通过命令去获取一些数据1.2 确定我们xml配置文件: 二、查看我们芯片支持的编码能力三、通过log去获取信息 这个文章的主要内容是为了后期性能方面的debug, 设计到前期的bringup则没有 一、通过命令去获取一些数据 获取媒体相关的参数: # getprop |…

失效的访问控制

文章目录 渗透测试漏洞原理失效的访问控制1. 失效的访问控制1.1 OWASP TOP 101.1.1 A5:2017-Broken Access Control1.1.2 A01:2021-Broken Access Control 1.2 失效的访问控制类别1.2.1 水平越权1.2.2 垂直越权 1.3 攻防案例1.3.1 DVWA越权 1.4 相关漏洞1.4.1 目录遍历1.4.2 未…

泥石流山体滑坡监控视觉识别检测算法

泥石流山体滑坡监控视觉识别检测算法通过yolov8python深度学习框架模型,泥石流山体滑坡监控视觉识别检测算法识别到泥石流及山体滑坡灾害事件的发生,算法会立即进行图像抓拍,并及时进行预警。Yolo的源码是用C实现的,但是好在Githu…

解决Echarts中双坐标轴分割错位问题

1、处理函数 /*** Description 刻度最大值* date 2023-08-30* param {any} isNaN(maxValue/1* returns {any}*/ export const getYAxisMax (maxValue): number > {if (isNaN(maxValue / 1) || maxValue / 1 < 10) {return 10;}const max: any Math.ceil(maxValue) ;c…