ssh 本地文件上传到服务器,定时上传 定时清理 文件时间阈值 定时开关。

public class SftpFileUploader {
    private List<String> localSourceDirectories;
    private String remoteDestinationDirectory;
    private String username;
    private String hostname;
    private int port;
    private String password;
    private long uploadIntervalMinutes;
    private boolean enableCleanup;
    private long cleanupIntervalMinutes;
    private Set<String> uploadedFiles;
    private long fileAgeThresholdMillis;

    public SftpFileUploader(List<String> localSourceDirectories, String remoteDestinationDirectory,
                            String username, String hostname, int port, String password,
                            long uploadIntervalMinutes, boolean enableCleanup, long cleanupIntervalMinutes, long fileAgeThresholdMinutes) {
        this.localSourceDirectories = localSourceDirectories;
        this.remoteDestinationDirectory = remoteDestinationDirectory;
        this.username = username;
        this.hostname = hostname;
        this.port = port;
        this.password = password;
        this.uploadIntervalMinutes = uploadIntervalMinutes;
        this.enableCleanup = enableCleanup;
        this.cleanupIntervalMinutes = cleanupIntervalMinutes;
        this.uploadedFiles = new HashSet<>();
        this.fileAgeThresholdMillis = fileAgeThresholdMinutes * 24 * 60 * 60 * 1000 ;
    }

    /**
     * 创建了一个周期性任务,用于上传文件,可以根据uploadIntervalMinutes参数的设置来控制上传频率。
     */
    public void startPeriodicUploadAndCleanup() {
        // lambda表达式创建 uploadFiles任务
        Runnable uploadTask = this::uploadFiles;
        uploadTask.run();

        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        //代码创建了一个大小为1的线程池,用于执行定时任务。代码创建了一个大小为1的线程池,用于执行定时任务。
        executor.scheduleAtFixedRate(uploadTask, uploadIntervalMinutes, uploadIntervalMinutes, TimeUnit.MINUTES);
        //uploadTask会被以固定的频率执行,这个频率由uploadIntervalMinutes参数确定,单位是分钟。这意味着每隔uploadIntervalMinutes分钟,都会执行一次文件上传操作。
        /**
                 *
                 * scheduleAtFixedRate方法接受四个参数:
                 *
                 * uploadTask: 要执行的任务,这里是this::uploadFiles。
                 * initialDelay: 首次执行任务的延迟时间,设为0表示立即开始执行。
                 * period: 每次执行任务的时间间隔。
                 * unit: 时间间隔的单位,这里是TimeUnit.MINUTES,表示时间间隔是以分钟为单位。
                 *
                 * */
        if (enableCleanup) {
            Runnable cleanupTask = this::clearFiles;
            executor.scheduleAtFixedRate(cleanupTask, cleanupIntervalMinutes, cleanupIntervalMinutes, TimeUnit.DAYS);
        }
    }

    /**
     * 通过SSH协议连接到远程服务器,使用SFTP通道实现了将本地文件上传到远程服务器的操作。
     * 在上传过程中,它还会创建远程子目录并递归地传输文件
     */
    private void uploadFiles() {
        for (String localSourceDirectory : localSourceDirectories) {
            JSch jsch = new JSch(); //用于处理安全的通信连接,主要用于SSH协议。
            Session session = null;  //声明了一个Session对象,用于表示与远程服务器的连接会话。
            ChannelSftp channelSftp = null;  //声明了一个ChannelSftp对象,表示SFTP(SSH File Transfer Protocol)通道,用于进行文件传输。

            try {
                session = jsch.getSession(username, hostname, port);
                session.setPassword(password);
                session.setConfig("StrictHostKeyChecking", "no");
                session.connect();

                channelSftp = (ChannelSftp) session.openChannel("sftp");
                //:配置会话以禁用严格的主机密钥检查,这可以在某些情况下简化连接建立过程。
                channelSftp.connect();

                File sourceDirectory = new File(localSourceDirectory);
                //创建一个File对象,表示本地源目录。
                String remoteSubDirectory = remoteDestinationDirectory + "/" + sourceDirectory.getName();
                //建一个远程子目录的路径,将文件上传到目标远程目录下的与本地源目录同名的子目录。
                createRemoteDirectories(channelSftp, sourceDirectory, remoteSubDirectory);
                //用于在远程服务器上递归地创建目录结构。
                uploadDirectory(channelSftp, sourceDirectory, remoteSubDirectory);

            } catch (JSchException | SftpException e) {
                System.err.println("Error uploading files from: " + localSourceDirectory);
                e.printStackTrace();
            } finally {
                if (channelSftp != null && channelSftp.isConnected()) {
                    channelSftp.disconnect(); //断开连接
                }
                if (session != null && session.isConnected()) {
                    session.disconnect();
                }
            }
        }
    }


    private void clearFiles() {
        if (!enableCleanup) {//检查是否启用了清理操作
            System.out.println("Clear files not enabled. Skipping.");
            return;
        }

        System.out.println("Clearing files from remote directories...");

        JSch jsch = new JSch();
        Session session = null;
        ChannelSftp channelSftp = null;

        try {
            session = jsch.getSession(username, hostname, port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();

            for (String localSourceDirectory : localSourceDirectories) {
                File sourceDirectory = new File(localSourceDirectory);
                String remoteSubDirectory = remoteDestinationDirectory + "/" + sourceDirectory.getName();
                clearRemoteDirectory(channelSftp, remoteSubDirectory);//清理远程目录
            }
        } catch (JSchException | SftpException e) {
            System.err.println("Error clearing remote files: " + e.getMessage());
            e.printStackTrace();
        } finally {
            if (channelSftp != null && channelSftp.isConnected()) {
                channelSftp.disconnect();
            }
            if (session != null && session.isConnected()) {
                session.disconnect();
            }
        }
    }

    private void clearRemoteDirectory(ChannelSftp channelSftp, String remoteDirectory) throws SftpException {
        Vector<ChannelSftp.LsEntry> entries = channelSftp.ls(remoteDirectory);
        //使用Vector的原因可能是为了处理文件列表的变化,并且在需要时可以动态添加和移除元素
        if (entries != null) {
            for (ChannelSftp.LsEntry entry : entries) {
                String fileName = entry.getFilename();
                if (!fileName.equals(".") && !fileName.equals("..")) {
                    //排除掉当前目录(.)和上级目录(..)的情况
                    String filePath = remoteDirectory + "/" + fileName;
                    //构建文件的完整路径。
                    if (entry.getAttrs().isDir()) {
                        clearRemoteDirectory(channelSftp, filePath);
                    } else {
                        //检查当前条目是否是一个目录。如果是目录,进入一个分支,如果是文件,进入另一个分支。
                        SftpATTRS attrs = entry.getAttrs();
                        long modificationTime = attrs.getMTime() * 1000L; // Convert to milliseconds
                       // 获取文件的修改时间并转换为毫秒。SFTP属性中的修改时间以秒为单位,乘以1000转换为毫秒。
                        if (enableCleanup) {
                            long currentTime = System.currentTimeMillis();
                            long fileAge = currentTime - modificationTime;
                            //计算文件的年龄

                            if (fileAge > fileAgeThresholdMillis) {
                                channelSftp.rm(filePath);
                                //检查文件的年龄是否超过了阈值。如果超过阈值,进入一个分支,如果没有超过,进入另一个分支
                                System.out.println("File '" + filePath + "' deleted from remote directory.");
                            } else {
                                System.out.println("File '" + filePath + "' retained in remote directory.");
                            }
                        }
                    }
                }
            }
        }
    }
    private void createRemoteDirectories(ChannelSftp channelSftp, File localDirectory, String remoteDirectory) throws SftpException {
        String[] directories = remoteDirectory.split("/");
        //将远程目录路径按照斜杠(/)进行分割,得到一个字符串数组,表示每个目录名称。
        StringBuilder dirPath = new StringBuilder();
        //创建一个StringBuilder对象,用于构建远程目录路径。
        for (String dir : directories) {
            if (dir.length() > 0) {
                //检查目录名称是否非空,以排除空白项。
                dirPath.append("/").append(dir);
                //将当前目录名称追加到dirPath中,构建出当前的远程目录路径。
                try {
                    channelSftp.cd(dirPath.toString());
                    //尝试切换到远程目录。如果目录不存在,将会抛出SftpException异常。
                } catch (SftpException e) {
                    channelSftp.mkdir(dirPath.toString());
                    //在远程服务器上创建目录
                    channelSftp.cd(dirPath.toString());
                    //切换到刚刚创建的远程目录。
                }
            }
        }

        File[] files = localDirectory.listFiles();
        //获取本地目录下的所有文件和子目录。
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    //检查当前项是否是一个目录。
                    String remoteSubDirectory = remoteDirectory + "/" + file.getName();
                    //构建一个远程子目录的路径。
                    createRemoteDirectories(channelSftp, file, remoteSubDirectory);
                }
            }
        }
    }

    /**
     * 递归地上传本地目录中的文件和子目录到远程服务器的指定目录
     */
    private void uploadDirectory(ChannelSftp channelSftp, File localDirectory, String remoteDirectory) throws SftpException {
        channelSftp.cd(remoteDirectory);

        File[] files = localDirectory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    uploadDirectory(channelSftp, file, remoteDirectory + "/" + file.getName());
                    //递归调用uploadDirectory方法,将当前本地目录的子目录上传到远程服务器的子目录
                } else if (file.isFile()) {
                    //如果当前项是一个文件,则进入这个分支。
                    if (!uploadedFiles.contains(file.getAbsolutePath())) {
                        //检查当前文件是否已经被上传,以避免重复上传。
                        uploadSingleFile(channelSftp, file, remoteDirectory);
                        //调用uploadSingleFile,用于将单个文件上传到远程目录。
                        uploadedFiles.add(file.getAbsolutePath());
                        //将已上传文件的路径添加到uploadedFiles列表中,以便进行记录和避免重复上传。
                    }
                }
            }
        }
    }

    private void uploadSingleFile(ChannelSftp channelSftp, File localFile, String remoteDirectory) throws SftpException {
        String remoteFilePath = remoteDirectory + "/" + localFile.getName();
        //构建远程文件的完整路径,将远程目录和本地文件名组合在一起。
        channelSftp.put(localFile.getAbsolutePath(), remoteFilePath, ChannelSftp.APPEND);
        //使用SFTP通道将本地文件上传到远程服务器的指定路径。
        // 获取本地文件的绝对路径,remoteFilePath是远程文件路径,ChannelSftp.APPEND表示如果文件已存在,则追加内容。
        System.out.println("File '" + localFile.getName() + "' uploaded successfully.");
        //如果远程文件已存在,则追加内容
    }
}

public static void main(String[] args) {
List localSourceDirectories = new ArrayList<>();
localSourceDirectories.add(“”);
localSourceDirectories.add(“”);

    String remoteDestinationDirectory = "";
    String username = "";
    String hostname = "1";
    int port = ;
    String password = "";
    long uploadIntervalMinutes = 1; // 每5分钟上传一次
    long cleanupIntervalMinutes  = 1; // 每30分钟清除一次文件
    boolean enableCleanup  = true; // 是否启用文件清除功能
    long fileAgeThresholdMinutes = 30; //分钟为单位设置所需的文件期限阈值



    SftpFileUploader fileUploader = new SftpFileUploader(localSourceDirectories, remoteDestinationDirectory,
            username, hostname, port, password, uploadIntervalMinutes, enableCleanup, cleanupIntervalMinutes, fileAgeThresholdMinutes);
    fileUploader.startPeriodicUploadAndCleanup();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值