两台linux之间互相传递文件

该Java类实现了通过JSch库连接到SFTP服务器,进行文件上传、删除和列举文件等操作。它使用ThreadLocal进行线程安全的SFTP客户端管理,并支持按日期过滤本地文件的上传。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.Collator;
import java.util.*;
import java.util.stream.Collectors;

import lombok.SneakyThrows;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

public class Ftp {
    //打印log日志
    private static final Log logger = LogFactory.getLog(Ftp.class);
    private static Date last_push_date = null;
    private Session sshSession;
    private ChannelSftp channel;
    private static ThreadLocal<Ftp> sftpLocal = new ThreadLocal<Ftp>();

    public Ftp(String host, int port, String username, String password) throws Exception {
        JSch jsch = new JSch();
        jsch.getSession(username, host, port);
        //根据用户名,密码,端口号获取session
        sshSession = jsch.getSession(username, host, port);
        sshSession.setPassword(password);
        //修改服务器/etc/ssh/sshd_config 中 GSSAPIAuthentication的值yes为no,解决用户不能远程登录
        sshSession.setConfig("userauth.gssapi-with-mic", "no");
        //为session对象设置properties,第一次访问服务器时不用输入yes
        sshSession.setConfig("StrictHostKeyChecking", "no");
        sshSession.connect();
        //获取sftp通道
        channel = (ChannelSftp) sshSession.openChannel("sftp");
        channel.connect();
        logger.info("连接ftp成功!" + sshSession);
    }

    /**
     * 是否已连接
     *
     * @return
     */
    public boolean isConnected() {
        return null != channel && channel.isConnected();
    }

    /**
     * 获取本地线程存储的sftp客户端
     *
     * @return
     * @throws Exception
     */
    public static Ftp getSftpUtil(String host, int port, String username, String password) throws Exception {
        //获取本地线程
        Ftp sftpUtil = sftpLocal.get();
        if (null == sftpUtil || !sftpUtil.isConnected()) {
            //将新连接防止本地线程,实现并发处理
            sftpLocal.set(new Ftp(host, port, username, password));
        }
        return sftpLocal.get();
    }

    /**
     * 释放本地线程存储的sftp客户端
     */
    public static void release() {
        if (null != sftpLocal.get()) {
            sftpLocal.get().closeChannel();
            logger.info("关闭连接" + sftpLocal.get().sshSession);
            sftpLocal.set(null);
        }
    }

    /**
     * 关闭通道
     *
     * @throws Exception
     */
    public void closeChannel() {
        if (null != channel) {
            try {
                channel.disconnect();
            } catch (Exception e) {
                logger.error("关闭SFTP通道发生异常:", e);
            }
        }
        if (null != sshSession) {
            try {
                sshSession.disconnect();
            } catch (Exception e) {
                logger.error("SFTP关闭 session异常:", e);
            }
        }
    }

    /**
     * @param directory  上传ftp的目录
     * @param uploadFile 本地文件目录
     */
    public void upload(String directory, String uploadFile) throws Exception {
        try {    //执行列表展示ls 命令
            channel.ls(directory);   //执行盘符切换cd 命令
            channel.cd(directory);
            //List<File> files = getFiles(uploadFile, new ArrayList<File>());
            List<File> files = Arrays.asList(new File(uploadFile));
            for (int i = 0; i < files.size(); i++) {
                File file = files.get(i);
                InputStream input = new BufferedInputStream(new FileInputStream(file));
                channel.put(input, file.getName());
                try {
                    if (input != null) input.close();
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error(file.getName() + "关闭文件时.....异常!" + e.getMessage());
                }
                if (file.exists()) {
                    //boolean b = file.delete();
                    logger.info(file.getName() + "文件上传完毕!");
                }
            }
        } catch (Exception e) {
            logger.error("【子目录创建中】:", e);
            //创建子目录
            channel.mkdir(directory);
        }
    }

    //获取文件
    public List<File> getFiles(String realpath, List<File> files) {
        File realFile = new File(realpath);
        if (realFile.isDirectory()) {
            File[] subfiles = realFile.listFiles(new FileFilter() {
                @Override
                public boolean accept(File file) {
                    if (null == last_push_date) {
                        return true;
                    } else {
                        long modifyDate = file.lastModified();
                        return modifyDate > last_push_date.getTime();
                    }
                }
            });
            for (File file : subfiles) {
                if (file.isDirectory()) {
                    getFiles(file.getAbsolutePath(), files);
                } else {
                    files.add(file);
                }
                if (null == last_push_date) {
                    last_push_date = new Date(file.lastModified());
                } else {
                    long modifyDate = file.lastModified();
                    if (modifyDate > last_push_date.getTime()) {
                        last_push_date = new Date(modifyDate);
                    }
                }
            }
        }
        return files;
    }


    /**
     * 删除文件
     *
     * @param deleteFile 要删除的文件路径,如:/root/test/saveFile/mylog.log
     */
    public void deleteFile(String deleteFile) {
        try {
            channel.rm(deleteFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 遍历目录下的文件,并选取名字字段长度为15的文件
     * @param remoteDir
     * @return
     */
    @SneakyThrows
    public List<String> allFileNames(String remoteDir) {
        List<String> list = new ArrayList<>();
        Vector vector = channel.ls(remoteDir);
        Iterator iterator = vector.iterator();
        while (iterator.hasNext()) {
            ChannelSftp.LsEntry file = (ChannelSftp.LsEntry) iterator.next();
            //文件名称
            String fileName = file.getFilename();
            if (15 == fileName.length()) {
                list.add(fileName);
            }
        }
        List<String> collect = list.stream().sorted((o1, o2) -> Collator.getInstance(Locale.TRADITIONAL_CHINESE).compare(o2, o1)).collect(Collectors.toList());
        List<String> listResult = new ArrayList<>();
        if (collect.size() > 3) {
            for (int i = 3; i < collect.size(); i++) {
                listResult.add(collect.get(i));
            }
        }
        return listResult;
    }

    @SneakyThrows
    public static void main(String[] args) {
        
    }


}
### 如何在两台 Ubuntu 22.04 服务器之间复制文件 为了实现两台 Ubuntu 22.04 服务器之间文件传输,可以采用多种方式。以下是几种常用的方法: #### 使用 `scp` 命令进行安全拷贝 `scp` 是一种基于 SSH 协议的安全文件传输工具,能够加密数据并验证身份。 ```bash scp /path/to/source_file username@remote_host:/path/to/destination_directory/ ``` 这条命令会将本地 `/path/to/source_file` 文件发送到远程主机上的指定路径下[^1]。 对于目录,则需加上 `-r` 参数表示递归操作整个文件夹的内容: ```bash scp -r /local/directory user@target_server:/remote/path/ ``` #### 利用 `rsync` 实现高效同步 相比起简单的 `cp` 或者 `scp`, `rsync` 提供更强大的功能集,在增量备份方面表现尤为出色。它只会传送两个位置间不同的部分,从而节省带宽资源。 基本语法如下所示: ```bash rsync -avz --progress /source/file_or_folder remote_user@remote_host:/destination/folder/ ``` 其中选项含义分别为: - `-a`: 归档模式, 表示递归处理并且保持原有属性不变; - `-v`: 显示详细过程信息; - `-z`: 启用压缩机制减少流量消耗; - `--progress`: 展示进度条以便观察传输状态; 当目标机器上已经存在相同名称的目标对象时,上述指令仅更新差异之处而不做全量重传。 #### 配置 Samba/CIFS 共享服务 另一种方案是通过设置 Windows 文件共享协议 (SMB),让 Linux 主机也能像局域网内的 PC 一样互相访问磁盘分区。这通常涉及到安装 samba 软件包以及配置相应的权限控制列表等步骤,适合长期稳定的需求场景。 以上就是一些常见的跨服务器迁移资料的方式介绍,具体选用哪一种取决于实际环境和个人偏好等因素考虑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值