SSHD实践(二)基于文件系统操作远程文件

Sftp
placeholder image
admin 发布于:2023-11-25 22:18:13
阅读:loading

前面介绍了使用Apache Mina SSHD的ChannelSftp实现对远程文件的操作,本文继续实践SSHD的系列文章,使用SftpFileSystem来实现对远程文件的操作

1.基本介绍

Apache Mina SSHD中的ChannelSftp和SftpFileSystem都可以操作远程服务器的文件,但它们之间有一些区别:

(1)架构:ChannelSftp是基于SSH协议实现的SFTP协议的客户端,而SftpFileSystem是基于VFS(Virtual File System)框架的实现,可以通过多种协议(包括SFTP)访问远程文件系统。

(2)使用方式:ChannelSftp通过创建一个SFTP通道与远程服务器进行通信,直接发送SFTP指令来对远程文件进行操作,如上传、下载、删除等。而SftpFileSystem通过创建一个文件系统对象,并通过提供的API来访问和操作远程文件,类似于使用本地文件系统相同的方式。

(3)功能扩展:由于SftpFileSystem是基于VFS框架,可以通过配置支持多种文件系统和文件协议,如SFTP、FTP、HTTP等。它还提供了更高级的功能,例如目录监听、文件缓存等,可以更方便地进行文件操作。

总的来说,ChannelSftp更加轻量级和直接,适合简单的SFTP文件操作;而SftpFileSystem则更加灵活和可扩展,适合复杂的文件系统操作,并且可以支持多种协议。选择使用哪种方式可以根据具体的需求和使用场景进行选择。

SftpFileSystem是Apache Mina SSHD中实现的基于VFS框架的SFTP文件系统,具有以下特征:

(1)多协议支持:SftpFileSystem支持多种协议,包括SFTP、FTP、HTTP等。这使得它可以通过不同协议访问远程文件系统,并提供统一的API进行操作。

(2)高级功能支持:SftpFileSystem提供了一些额外的高级功能,例如目录监听和文件缓存。目录监听可以实现对远程目录的实时监控,当目录中的文件发生变化时,可以及时收到通知。文件缓存可以在本地缓存一部分远程文件,提高访问速度。

(3)与VFS集成:SftpFileSystem是基于VFS框架的实现,可以与VFS的其他功能进行集成。VFS提供了一些通用的文件系统操作API,如读取文件、写入文件、列出目录等,可以方便地在SftpFileSystem中使用。

(4)安全性:由于基于SSH协议,SftpFileSystem提供了安全的文件传输和身份验证机制。通过SSH的加密通信,可以保障数据的安全性。

(5)可扩展性:由于基于VFS框架,SftpFileSystem可以方便扩展支持其他协议和文件系统。可以通过定制来满足特定的需求,例如支持其他文件存储系统或加密算法等。

总的来说,SftpFileSystem提供了一套统一的API和一些额外的高级功能,方便用户访问和操作远程文件系统。它具有灵活性和可扩展性,适用于复杂的文件系统操作和要求更高级功能的场景。

2.代码示例

package cn.chendd.sshd;

import ...;

/**
 * Exec Test
 *
 * @author chendd
 * @date 2023/11/20 19:10
 */
@RunWith(JUnit4.class)
public class SftpFileSystemTest {

    /**
     * 文件信息获取
     */
    @Test
    public void fileTest() throws IOException {
        function((sshClient, session, fileSystem) -> {
            final SftpPath path = fileSystem.getPath("/app/arthas/arthas-class/nohup.out");
            System.out.println("文件名称:" + path.getFileName());
            System.out.println("文件大小:" + Files.size(path));
            //注:因时区差异需要设置小时+8
            System.out.println("最后更新时间:" + Files.getLastModifiedTime(path));
            System.out.println("文件权限:" + PosixFilePermissions.toString(Files.getPosixFilePermissions(path)));
        });
    }

    /**
     * 文件夹信息获取
     */
    @Test
    public void folderTest() throws IOException {
        function((sshClient, session, fileSystem) -> {
            final SftpPath defaultDir = fileSystem.getDefaultDir();
            System.out.println("获取系统默认文件夹:" + defaultDir.toRealPath());
            final SftpPath path = fileSystem.getPath("/app/arthas/arthas-class/");
            System.out.println("文件夹名称:" + path.getFileName());
            System.out.println("文件夹大小:" + Files.size(path));
            //注:因时区差异需要设置小时+8
            System.out.println("最后更新时间:" + Files.getLastModifiedTime(path));
            System.out.println("文件夹权限:" + PosixFilePermissions.toString(Files.getPosixFilePermissions(path)));

            System.out.println("=========================列出文件夹中全部======================");
            try (final Stream<Path> stream = Files.list(path)) {
                final List<Path> paths = stream.collect(Collectors.toList());
                for (Path p : paths) {
                    if (Files.isDirectory(p)) {
                        System.out.println("文件夹:" + p.getFileName());
                    } else {
                        System.out.println("文件:  " + p.getFileName());
                    }
                }
            }
            System.out.println("=========================列出文件夹中全部======================");
        });
    }

    /**
     * 创建多层级文件夹目录
     */
    @Test
    public void mkdirsTest() throws IOException {
        function((sshClient, session, fileSystem) -> {
            final SftpPath path = fileSystem.getPath("/app/arthas/arthas-class/a/b/c/");
            Files.createDirectories(path);
        });
    }

    protected void function(Runnable runnable) throws IOException {
        SshClient sshClient = SshClient.setUpDefaultClient();
        sshClient.start();

        SftpParam param = new SftpParam();
        ClientSession session = sshClient.connect(param.getUsername(), param.getHost(), param.getPort()).verify().getSession();
        session.addPasswordIdentity(param.getPassword());
        session.auth().verify();
        SftpFileSystem fileSystem = SftpClientFactory.instance().createSftpFileSystem(session);

        runnable.run(sshClient , session , fileSystem);

        fileSystem.close();
        session.close();
        sshClient.close();
    }

    @FunctionalInterface
    protected interface Runnable {

        void run(SshClient sshClient , ClientSession session , SftpFileSystem fileSystem) throws IOException;

    }
    
    //......省略上传、下载、删除等方法

}

3.示例说明

(1)代码为示例,写的比较随意,某些IO资源的释放应以更严格的形式编写;

(2)示例实现了与ChannelSftp一样的全部实现:

   ① 文件上传;

   ② 文件下载;

   ③ 文件(夹)删除;

   ④ 文件(夹)重命名

   ⑤ 文件(夹)路径是文件还是文件夹

   ⑥ 文件夹路径创建

   ⑦ 文件夹中的文件列表获取

4.示例预览

SSHD文件系统-含水印.gif


5.其它说明

(1)本次实践Apache MINA SSHD共计四块知识,分别是使用Sftp访问远程服务器、Exec执行远程服务器命令、Shell执行远程服务器命令、SftpFileSystem,至于它还可以作用于的端口转发等功能不做摸索;

(2)本文实现了基于SSHD SftpFileSystem的文件的上传、下载、删除、重命名、文件列表、路径是否存在等多个常用的功能,完整示例代码可见《附件下载.zip》;

(3)工具类代码的封装像极了使用原生JDBC操作数据库的实现:① 每个方法都需要处理异常;② 每次操作都获取 Connection连接,使用完后关闭连接;

(4)工具类代码的封装应该以池化的形式,可以使用Apache Commons pool组件进行连接池的方式管理,在实际应用中将会更加科学;


 点赞


 发表评论

当前回复:作者

 评论列表


留言区