Implementing SFTP File Management in WebShell

· 3 min read · 429 Words · -Views -Comments

After enabling web-based terminal access via WebShell, users also need visual file management: upload/download, permission changes, inline editing, etc. Here’s a summary of the implementation.

ssh2 + ssh2-sftp-client

After solving the terminal connection with ssh2, use ssh2-sftp-client to perform file operations:

  1. list to fetch file lists
    • Returns file type, name, owner uid, group gid, size, atime, mtime
    • For symlinks, type is l; hard links appear as -
  2. get/put for streaming upload/download
  3. rename to rename files
  4. delete to delete files
  5. stat to get file info
  6. mkdir to create directories
  7. rename to rename files

These cover the basics, but there are additional concerns.

Issues

  1. Check whether the current user has permissions

First determine the current user’s uid/gid. Use ssh2.exec to run id to obtain them. Then compare with the file’s uid/gid from list/stat to infer permissions.

  1. User list

The GUI needs to change file ownership. Since list/stat provides uid/gid, you only need a user list. For example:

# Output format:
# root,0
grep /bin/bash /etc/passwd | awk -F: '{print $1 "," $3}'
  1. Hidden files in lists

    To hide dotfiles, pass a filter (regex in older versions) when listing:

    conn.list(path, /^[^.]/);
    

    Note: SFTP doesn’t support server-side filtering; ssh2 still fetches all entries and filters client-side. In ssh2-sftp-client v9, list switched from regex to a callback filter, which still works for this.

  2. Use the terminal session’s current working directory as the default open path

    Strictly speaking this is terminal-side, not SFTP. But it greatly improves UX. Implement via terminal hooks: after each command, run pwd and send the result to the client. The client parses and caches the path; when opening SFTP, pass it as the initial path.

    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);CurrentUser=$USER;\x7"; }
    

Beyond SFTP, there are other cases such as kubectl.

kubectl

If managing containers via kubectl, SFTP won’t work. You’ll need to execute commands and parse the results.

  1. Use ls and friends to list files. Note that commands differ across container OSes and may need branching.

    ls -l --time-style=full-iso /
    
    • Add -A to hide dotfiles
    • --time-style=full-iso stabilizes time format regardless of system locale
  2. Avoid stat for file properties since output can be localized (e.g., “directory” differs by locale). Prefer ls with -d so the result is a single entry for the target file/dir. Also note that unlike ls -l, there’s no first-line summary.

    ls -ld --time-style=full-iso /
    

Final Thoughts

  • The above outlines the main path; real-world implementations are more complex, but the key points are here.
  • After WebShell shipped file management, long-term observations showed it became the No.1 used feature—clearly very important.
Authors
Developer, digital product enthusiast, tinkerer, sharer, open source lover