WebShell中实现sz/rz上传下载
·
2 min read
最近支持上传下载,做了
lrzsz
的调研开发,这里总结下
使用说明
首先了解下szrz功能
sz支持
多文件下载
rz支持
多文件上传
,上传目标目录为当前命中执行目录,rz
不支持文件夹上传
rz上传针对已存在文件,会有标记信息说明
针对体积大小,无法传输大于
4G
的文件下载中/上传中
支持取消
szrz系统支持
- 服务器默认是没有安装 lrzsz 工具的,需要手动安装
- 不是所有工具都支持 rz 与 sz,必须支持 ZModem 协议才行,安装脚本如下
# MacOS
brew install lrzsz
brew remove lrzsz
# CentOS
yum install lrzsz
yum remove lrzsz
## 跨平台安装脚本
sudo sh -c "$(curl -fsSL https://gist.githubusercontent.com/alanhe421/6a299b815f4dd3d242abc16b8be6b861/raw/dbe1497208f1d968ed8b67cad09c596e35c5be9c/install-package-lrzsz.sh)"
官方demo
zmodem.js作者提供了demo,方便了解。为了保证demo正常运行,需要以下操作
- demo地址:https://github.com/FGasper/xterm.js/tree/zmodem
- node版本切换到
v8
重新执行npm i
- 启动后访问http://127.0.0.1:3000/
功能实现
上述作者的demo比较简单,并未提及一些功能,这里贴下关键实现。完整例子戳这里
sz取消下载
上传直接唤起的资源管理器选择框,在取消后,JS层面无法得知,因此只能用户主观再按ctrl c
取消,之后发送abort命令进行取消。
activeZsession._skip();
除了上述方法外,还有个办法就是自行增加上传弹窗,让用户点击时再调用abort即可。
rz取消上传
// 停止发送数据块,xfer.send(chunk)
await zsession.close()
上传-文件已存在
xfer识别为空即表示服务端拒绝上传,目前发现原因是文件存在,不排除有其它可能性。
const xfer = await zsession.send_offer(curb);
if(!xfer){
showMessage(`${xfer.get_details().name} rejected.`);
}
进度打印
针对上传,根据已发送大小/总大小计算进度,针对下载则是接收的大小/总大小。
上传进度,循环直接打印进度会不work,原因是xterm并非同步打印,为了解决该问题,增加delay即可。
await new Promise(resolve => window.setTimeout(resolve, 0));
考虑到体验,可以除了进度之外显示下进度条, xterm.write时候不要\n换行显示即可。
function getProgressBar(total, current) {
if (total < current) {
throw new Error('total must be greater than current');
}
const progressBarLength = 40; // 进度条的长度
const progress = Math.floor((current / total) * progressBarLength);
const empty = progressBarLength - progress;
const progressBar = '█'.repeat(progress) + '░'.repeat(empty);
return `(${progressBar}) ${((current / total) * 100).toFixed(2)}%`;
}