gitee地址 https://gitee.com/zxadmin/luckysheet-phpserver
此项目目前定义为对接失败,当然Luckysheet也可以去除掉加密的部分,直接json通信就没问题
2022年9月21日09:41:18
终于解决了webman对接问题
因为现在php8 default_charset = "UTF-8" PHP的默认处理字符集是utf-8
但是gzip的默认字符集是 ISO-8859-1, gzdecode函数处理也需要 ISO-8859-1字符集
参考了java版本的代码发现他也是转还了字符集
public static String uncompress(String str) throws IOException {
if (str == null || str.length() == 0) {
return str;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes("ISO-8859-1"));
GZIPInputStream gunzip = new GZIPInputStream(in);
byte[] buffer = new byte[256];
int n;
while ((n = gunzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
// toString()使用平台默认编码,也可以显式的指定如toString("GBK")
return out.toString();
}
str.getBytes("ISO-8859-1"),我就尝试转换了一下
$content = mb_convert_encoding($data, 'ISO-8859-1', 'utf-8');
var_dump(json_decode(urldecode(gzdecode($content)), true));
然后就解析成功了,现在php对接Luckysheet也可以了
luckysheet 是前端测试代码
luckysheet/pako/examples/browser.html pako是加密测试代码
luckysheet/pako/examples/browser_post.html pako是加密测试代码
luckysheet/pako/examples/browser_socket.html pako是加密测试代码
Luckysheet的 share多人协作数据发送对接流程:
Luckysheet的配置
$(function () {
// According to the browser language
var lang = luckysheetDemoUtil.language() === 'zh' ? 'zh' : 'en';
//var isShare = luckysheetDemoUtil.getRequest().share; // '?share=1' opens the collaborative editing mode
//var gridKey = luckysheetDemoUtil.getRequest().gridKey; // workbook id for collaborative editing, or directly define here
var isShare = 1; // '?share=1' opens the collaborative editing mode
var gridKey = "1079500#-8803#7c45f52b7d01486d88bc53cb17dcd2xc"; // workbook id for collaborative editing, or directly define here
var options = null;
if (isShare || gridKey) {
// http://localhost:3000/?gridKey=12eyy789-kk45ofid-23737245
if (!gridKey) {
alert('If gridKey is not provided in the address bar, please add it in the source code')
}
options = {
container: "luckysheet",
lang: lang,
allowUpdate: true,
updateImageUrl: "http://192.168.154.131" + "/luckysheet/updateImg",
updateUrl: "ws://192.168.154.131:8888",
gridKey: gridKey,
loadUrl: "http://192.168.154.131" + "/luckysheet/load",
loadSheetUrl: "http://192.168.154.131" + "/luckysheet/loadsheet"
}
} else {
console.log(1111111);
}
luckysheet.create(options);
})
1,选请求 luckysheet/load接口
接口返回
[{"color":"","list_id":"1079500#-8803#7c45f52b7d01486d88bc53cb17dcd2xc","column":60,"index":"1","jfgird_select_save":[{"top_move":180,"top":180,"left":222,"column_focus":3,"width":73,"column":[3,3],"left_move":222,"width_move":73,"row":[9,9],"row_focus":9,"height_move":19,"height":19}],"rh_height":1790,"visibledatacolumn":[],"scrollTop":0,"block_id":"fblock","rowsplit":[],"visibledatarow":[],"jfgrid_selection_range":{},"name":"Sheet1","celldata":[],"ch_width":4748,"row":84,"scrollLeft":0,"id":350081777752215552,"chart":[],"config":{},"order":0,"status":1},{"color":"","list_id":"1079500#-8803#7c45f52b7d01486d88bc53cb17dcd2xc","column":60,"index":"2","jfgird_select_save":[],"rh_height":1790,"visibledatacolumn":[],"scrollTop":0,"block_id":"fblock","rowsplit":[],"visibledatarow":[],"jfgrid_selection_range":{},"name":"Sheet2","ch_width":4748,"row":84,"scrollLeft":0,"id":350081777752215553,"chart":[],"config":{},"order":1,"status":0},{"color":"","list_id":"1079500#-8803#7c45f52b7d01486d88bc53cb17dcd2xc","column":60,"index":"3","jfgird_select_save":[],"rh_height":1790,"visibledatacolumn":[],"scrollTop":0,"block_id":"fblock","rowsplit":[],"visibledatarow":[],"jfgrid_selection_range":{},"name":"Sheet3","ch_width":4748,"row":84,"scrollLeft":0,"id":350081777752215554,"chart":[],"config":{},"order":2,"status":0}]
2,就会建websocket通信 ws://192.168.154.131:8888
$data1 = '{"message":"连接成功","type":"0","status":"0"}';
$data2 = '{"data":"","message":"反馈以前操作信息","type":"4","status":"0"}';
发送个前端
这样就可以一share多人协作模式正常打开了
3,如果操作Luckysheet会触发 saveParam方法
通过
let msg = pako.gzip(encodeURIComponent(JSON.stringify(d)), { to: "string" });
if(_this.websocket!=null){
_this.websocket.send(msg);
}
发送给服务端,这个是经过pako加密的,服务端需要先解开数据加密,然后根据
_this.saveParam("rv", sheetIndex, v, { "range": { "row": [str, edr], "column": [c1, c2] } });
if(i == n - 1){
_this.saveParam("rv_end", sheetIndex, null);
}
告诉客户端返回不通过的status,需要查看 server.js的源代码
返回数据格式
{
createTime: 命令发送时间
data:{} 修改的命令
id: "7a" websocket的id
returnMessage: "success"
status: "0" 0告诉前端需要根据data的命令修改 1无意义
type: 0:连接成功,1:发送给当前连接的用户,2:发送信息给其他用户,3:发送选区位置信息,999:用户连接断开
username: 用户名
}
webman的时候需要返回这种格式的json给当前连接的客户端,然后广播给其他客户端,这样就完成了多人协作的基本功能
<?php
namespace process;
use Webman\Channel\Client;
use Workerman\Connection\TcpConnection;
use Workerman\Timer;
class Luckysheet
{
protected $connections = [];
public function __construct()
{
}
public function onConnect(TcpConnection $connection)
{
echo "onConnect\n";
}
public function onWebSocketConnect(TcpConnection $connection, $http_buffer)
{
echo "onWebSocketConnect\n";
$data1 = '{"message":"连接成功","type":"0","status":"0"}';
$connection->send($data1);
$data2 = '{"data":"","message":"反馈以前操作信息","type":"4","status":"0"}';
$connection->send($data2);
$key = $this->getUid($connection->getLocalIp(), $connection->getLocalPort(), $connection->worker->workerId, $connection->worker->id, $connection->id);
$this->connections[$key] = $connection;
}
/*
* {
createTime: 命令发送时间
data:{} 修改的命令
id: "7a" websocket的id
returnMessage: "success"
status: "0" 0告诉前端需要根据data的命令修改 1无意义
type: 0:连接成功,1:发送给当前连接的用户,2:发送信息给其他用户,3:发送选区位置信息,999:用户连接断开
username: 用户名
}
*/
public function onMessage(TcpConnection $connection, $data)
{
$key = $this->getUid($connection->getLocalIp(), $connection->getLocalPort(), $connection->worker->workerId, $connection->worker->id, $connection->id);
$return = [];
$return['createTime'] = time();
$return['data'] = null;
$return['returnMessage'] = 'success';
$return['status'] = '1';
$return['type'] = 0;
$return['id'] = $key;
$return['username'] = $key;
if ($data == 'rub') {
//心跳不回复
} else {
//解析数据出错,目前不清楚是为什么,不能解析,就无法 给$return 返回对应的数据
$out = json_decode(urldecode(gzdecode($data)), true);
//返回错误是 gzdecode data error
//单线程版本写法,多线程需要channel通信
$this->broadcast($key, $out);
$connection->send(json_encode($return));
}
}
public function onClose(TcpConnection $connection)
{
echo "onClose\n";
}
public function getUid($local_ip, $local_port, $workerId, $worker_id, $connection_id)
{
$str = $local_ip . $local_port . $workerId . $worker_id . $connection_id;
return md5($str);
}
public function broadcast($key, $data)
{
foreach ($this->connections as $k => $connection) {
if ($k !== $key) {
$connection->send($data);
}
}
}
}
目前在webman的websocket去解析 加密数据
但是在其他地方都可以解析出来
1,java版本解析没问题
2,laravel中
3,webman api模式
测试前端
const obj = [
{ foo: 'bar', baz: 'baz' },
{ abra: 1, cadabra: null }
]
let msg = pako.gzip(encodeURIComponent(JSON.stringify(obj)), { to: "string" });
console.log(msg)
function send(msg) {
var xhr = new XMLHttpRequest;
xhr.open('POST', 'http://www.yd.com/open/test', true);
xhr.send(msg);
//setTimeout(send, 5000);
}
send(msg);
后端代码基本一样
webman api
$in = $request->rawBody();
$res = json_decode(urldecode(gzdecode($in)), true);
return json($res);
laravel
$in = file_get_contents("php://input");
$res = json_decode(urldecode(gzdecode($in)), true);
socket测试,没问题
<script src="./../dist/pako.js"></script>
<script>
const obj = [
{ foo: 'bar', baz: 'baz' },
{ abra: 1, cadabra: null }
]
let result = pako.gzip(encodeURIComponent(JSON.stringify(obj)), { to: "string" });
ws = new WebSocket('ws://192.168.154.140:8888');
ws.onopen = function () {
ws.send(result);
}
</script>
java版本的话,参考
https://gitee.com/chuanshanjun/luckysheet-saved-in-recovery