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

rrweb录制用户的操作过程,并上传服务端_第1张图片

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

你可能感兴趣的:(总结,状态模式)