WebShell中实现右键文件下载

最近WebShell支持了右键下载,这里总结下实现过程

说明

  1. 当前仅支持下载文件,暂不支持文件夹
  2. 使用技术栈

技术实现

  1. 文本选中

    • xterm.js支持双击选中部分文本,匹配模式为word,因此如果如果文件夹名称是hello world,那只能自己再拖拽选择了。
    • shell中无法具体直接识别字符是不是文件,文件夹还是PS1这类的提示符,通过Shell配置只是可以控制颜色,但是反向根据颜色来判断是否是文件夹这是没用的,毕竟主题不同,颜色值也会不同。
  2. 文件所在目录即Current Working Directory

    • 这个需要Shell integration来解决,本质就是函数钩子,在每次执行一条命令结束时获取当前所在目录并发送消息出来。同时目录信息存储在隐藏字符中避免显示到终端上,程序中我们持续提取当前目录即可。

      1
      2
      3
      4
      source /usr/local/bash-precmd/bash-preexec.sh
      preexec() { printf "\x1B]1337;PreExec;Timestamp=$(date +%s);\x7"; }

      precmd() { printf "\x1B]1337;PostExec;Exit=$?;CurrentDir=$(pwd);Timestamp=$(date +%s);\x7"; }
    • 有了目录,同时支持选中文件,最基础的执行下载就OK了。

  3. 目录历史

    • 如果说用户选中最新一行的文件那没问题,但是终端下,每一行信息所在的目录是不同的,因此CWD要持续记录
    • 记录的标准并不应该按照xterm显示终端的行号进行一对一,因为比如一个ls命令显示文件列表,可能会具体显示为2行,因此最佳的方式是CWD针对这次写入终端信息所在的N行对齐即可
  4. 获取文件信息

    • 选中文本并不能保证一定是个文件,因此我们还需要根据选中文本能够识别出文件类型/大小/权限等等。ssh2-sftp-client下有stat方法可以支持

    • stat方法返回的mode值是二进制,比如33279,需要转化后才可以具体指导rwx权限

      1
      (rslt.mode& parseInt('777', 8)).toString(8)
    • 针对软链接类型文件,list接口返回的类型为l,但是stat方法返回的isSymbolicLink却是false,这种情况两者不一致,目前还没有解决办法。

  5. 文件下载

    • 在明确了可以下载的前提下,执行下载方法就很多了。ssh2-sftp-client下提供的get,或者fastGet均可实现下载,如果是终端连接的ssh会话也可以走sz下载均可。
    • 空文件下载以上方法均支持,只是注意针对get的流方法,该流的onData数据不会被触发,但end方法可以正常执行。

写在最后

支持了右键下载,下载的体验就会更舒服流畅,但背后的下载执行仍然是跟其它下载方式一致。