使用ftp,sftp多线程给各省同步文件信息 一

开发环境如果没有ftp 服务器的话,可以下载一个serv-U 挺好用的;运行起来就行一个本地的ftp服务器;

1.需求 给各省根据配置表以ftp或sftp协议的方式,多线程 定时任务 给各省同步所需的数据;

设计表:业务基本配置表:配置对外提供哪些业务;

省份 业务关系表:配合 业务和省份的关系,配置 哪些省份需要同步哪些业务数据;

省份 业务 模板关系表:针对模板信息,根据 省份 业务 以及模板 配置对外提供的哪些数据;

省份 文件路径表:配置省份 及 ftp或sftp 的文件夹 路径 及传输协议;

省份 ip 端口号 用户名 密码表:记录ftp sftp的ip端口 用户名 密码等信息;用来初始化 链接;

等等等表....

2 ,设计:ftp sftp 的链接创建 设计6个类:涉及接口,抽象类,工程类,

优点:需要增加 传输协议例如 本来只是ftp后来增加sftp 或者htttp等,只需要 增加 实现类就可以;不需要改动之前的代码逻辑;

1顶级抽象类:
/**
 * Created by 12 on 2018/8/11.
 */
@Component
public abstract class AbstractFTPFileTransfer implements FileTransferInterface{

}

2接口类:定义通用方法:

public interface FileTransferInterface {
    public void init(HashMap connectInfo);
    public void upload(String  fileName, InputStream fileInputStream);
    public void rename(String ftppathName,String newftpPathName);
    public void close();

}

3工厂类:提供初始化链接以及 提供一些接口;

@Component
public class FTPTransterFactory {
    private static final Logger logger = LoggerFactory.getLogger(FTPTransterFactory.class);
    @Reference
    private IKmSyncFtpPathSV iKmSyncFtpPathSV;
    @Reference
    private IKmSyncCollectLogSV iKmSyncCollectLogSV;

    @Reference
    private IKmSyncUploadLogSV iKmSyncUploadLogSV;

    @Reference
    private IKmTaskSV kmTaskSV;

//    public Map<String, FileTransferInterface> getFileTransferInterface(List<HashMap<String, String>> map) {
       FileTransferInterface  ftpInfotr  = AppContext.getBean((String) ftpInfo.getTrsfAgrmt());
       ftpInfotr.init();
//        return new HashMap<String, FileTransferInterface>();
//    }
    HashMap connectInfo;
    public FileTransferInterface getFileTransferInterface(HashMap pathAndProvince) {
        String pathId = String.valueOf(pathAndProvince.get("pathId"));
        connectInfo = iKmSyncFtpPathSV.getConnectInfo(pathId);
        String connectClassName = String.valueOf(connectInfo.get("connectClassName"));
        FileTransferInterface connectObj = AppContext.getBean(connectClassName);
        return connectObj;
    }

    public HashMap getConnectInfo(){
        return  connectInfo;
    }

    public IKmSyncCollectLogSV getIkmSyncCollectLogSv(){
        return  iKmSyncCollectLogSV;
    }

    public IKmSyncUploadLogSV getiKmSyncUploadLogSV(){
        return iKmSyncUploadLogSV;
    }

    public IKmTaskSV getKmTaskSV(){return kmTaskSV;}
}

4,5 ftp 和sftp 的具体类:因为涉及多线程调用,所以需要加@scope

@Component("fTPFileTransfer")
@Scope(value = "prototype")
public class FTPFileTransfer extends AbstractFTPFileTransfer {
    private static final com.cmos.core.logger.Logger logger = LoggerFactory.getLogger(FTPFileTransfer.class);

    private FtpUtil ftpUtil = null;
    private  FTPClient ftpClient;
    @Override
    public void init(HashMap connectInfo){
        try{
            String ipValue = String.valueOf(connectInfo.get("ipValue"));
            int portValue = Integer.parseInt(String.valueOf(connectInfo.get("portValue")));
            String userName = String.valueOf(connectInfo.get("userName"));
            String password = String.valueOf(connectInfo.get("password"));
            String catalogPath = String.valueOf(connectInfo.get("catalogPath"));
            ftpUtil = new FtpUtil();
            ftpClient =  ftpUtil.initFtpClient(ipValue,portValue,userName,password);
            boolean changeFlag = ftpClient.changeWorkingDirectory(catalogPath);
            if (!changeFlag){
                logger.error("ftp链接初始化,变更到指定目录失败");
                return;
            }
        }catch (Exception e){
            logger.error("ftp链接初始化:"+e);
        }
    }

    @Override
    public void upload(String  tempFileName, InputStream fileInputStream) {
        try {
            ftpClient.storeFile(tempFileName,fileInputStream);
        }catch (Exception e){
            logger.error("ftp上传文件异常:"+e);
        }
    }

    @Override
    public void rename(String tempFileName, String fileName) {
        try {
            ftpClient.rename(tempFileName, fileName);
        }catch (Exception e){
            logger.error("ftp修改文件名称异常"+e);
        }
    }

    @Override
    public void close() {
        try {
            ftpClient.logout();
            ftpClient.disconnect();
        }catch (Exception e ){
            logger.error("ftp退出异常"+e);
        }
    }
}

@Component("sFTPFileTransfer")
@Scope(value = "prototype")
public class SFTPFileTransfer extends AbstractFTPFileTransfer{


    private static final com.cmos.core.logger.Logger logger = LoggerFactory.getLogger(SFTPFileTransfer.class);

    private MySFtp mySFtp = null;
    private ChannelSftp channelSftp = null;

    @Override
    public void init(HashMap connectInfo) {
        try{
            String ipValue = String.valueOf(connectInfo.get("ipValue"));
            int portValue = Integer.parseInt(String.valueOf(connectInfo.get("portValue")));
            String userName = String.valueOf(connectInfo.get("userName"));
            String password = String.valueOf(connectInfo.get("password"));
            String catalogPath = String.valueOf(connectInfo.get("catalogPath"));
            mySFtp = new MySFtp();
            channelSftp = mySFtp.connect(ipValue,portValue,userName,password);
            channelSftp.cd(catalogPath);
        }catch (Exception e){
            logger.error("sftp链接初始化:"+e);
        }
    }

    @Override
    public void upload(String  tempFileName, InputStream fileInputStream) {
        try {
            channelSftp.put(fileInputStream,tempFileName);
        }catch (Exception e){
            logger.error("sftp上传文件异常:"+e);
        }
    }

    @Override
    public void rename(String tempFileName, String fileName) {
        try {
           channelSftp.rename(tempFileName,fileName);
        }catch (Exception e){
            logger.error("sftp修改文件名称异常"+e);
        }
    }

    @Override
    public void close() {
        try {
            channelSftp.exit();
        }catch (Exception e ){
            logger.error("sftp退出异常"+e);
        }
    }
}
6 ftp sftp 工具类:

public class FtpUtil {
    
    private static final Logger logger = LoggerFactory.getLogger(FtpUtil.class);
    private static FTPClient ftpClient = null;
    private String _host = null;
    private int _port = 0;
    private String _username = null;
    private String _password = null;
    private String _remotePath = null;
    public static final String FILE_SPEARATROR = "/"; // 路径分隔符
    private static String LOCAL_CHARSET = "GBK"; // 本地字符编码
    private static String SERVER_CHARSET = "ISO-8859-1";// FTP协议里面,规定文件名编码为iso-8859-1

    public FTPClient initFtpClient(String ip, int port, String username, String password) {
        long start = System.currentTimeMillis();
        ftpClient = new FTPClient();
        ftpClient.setControlEncoding("utf-8");
        try {
            ftpClient.connect(ip, port);
            //登录ftp服务器
            ftpClient.login(username, password);
            //是否成功登录服务器
            int replyCode = ftpClient.getReplyCode();
            logger.info("reply == " + replyCode);
            //设置被动模式
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            if(!FTPReply.isPositiveCompletion(replyCode)){
                ftpClient.disconnect();
                logger.error("connect failed...ftp服务器:" + ip + ":" + port);
                return null;
            } else {
                logger.info("connect successful...ftp服务器:" + ip + ":" + port);
            }
            long end = System.currentTimeMillis();
            logger.info("ftp connect time:" +(end - start));

        } catch (IOException e) {
            logger.error("ftp连接失败:" + ip + ":" + port, e);
            return null;
        }
        return ftpClient;
    }

    //判断ftp服务器文件是否存在
    public boolean existFile(String path)  {
        boolean flag = false;
        FTPFile[] ftpFileArr;
        try {
            ftpFileArr = ftpClient.listFiles(path);
        } catch (IOException e) {
            logger.error("读取文件失败");
            return flag;
        }
        if (ftpFileArr.length > 0) {
            flag = true;
        }
        return flag;
    }

    /**
     * 退出ftp
     */
    public void logout() {
        try {
            ftpClient.logout();
            ftpClient.disconnect();
        } catch (IOException e) {
            logger.error("logout ftp fail ....." + e.getMessage(), e);
        }
    }

    /**
     * 空的构造方法
     */
    public FtpUtil(){
    }

    /**
     * 创建实例对象
     * @param hostIp
     * @param port
     * @param username
     * @param password
     * @throws IOException
     */
    public FtpUtil(String hostIp, int port, String username, String password) throws IOException {
        logger.debug("hostIp --> " + hostIp + " , port -->" + port + " , username -->" + username + " , password -->" + password);
        initFtpClient(hostIp,port,username,password);
        _host = hostIp;
        _port = port;
        _username = username;
        _password = password;
    }

    /**
     * 创建一个带路径的实例对象
     * @param hostIp
     * @param port
     * @param username
     * @param password
     * @param remotepath
     * @throws IOException
     */
    public FtpUtil(String hostIp, int port, String username, String password, String remotepath) throws IOException {
        logger.debug("hostIp --> " + hostIp + " , port -->" + port + " , username -->" + username + " , password -->" + password + " , remotepath -->" + remotepath);
        initFtpClient(hostIp,port,username,password);
        ftpClient.changeWorkingDirectory(remotepath);
        _host = hostIp;
        _port = port;
        _username = username;
        _password = password;
        _remotePath = remotepath;
    }

    /**
     * 上传文件
     * @param remotePath 路径
     * @param filename 文件名
     * @param input 文件流
     * @return
     */
    public boolean uploadFile(String remotePath, String filename,InputStream input) {
        boolean result = false;
        try {
            if(!ftpClient.isConnected()){
                this.forceReconnect();
            }
            // 检验是否连接成功
            boolean isConnected = this.isConnected();
            //注意:有的FTP是需要先发送CLNT版本号的
            if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
                setLocalCharset("UTF-8");
            }
            ftpClient.setControlEncoding(LOCAL_CHARSET);
            ftpClient.enterLocalPassiveMode();// 设置被动模式
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            // 判断链接是否可用
            if(ftpClient.isAvailable()){
                // 切换到正确的目录,无则创建
                changeToRightDir(remotePath);

                // 上传
                result = ftpClient.storeFile(new String(filename.getBytes(LOCAL_CHARSET), SERVER_CHARSET), input);
                if (result) {

                }
            }
            input.close();
            ftpClient.logout();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ioe) {
                    logger.error(ioe.getMessage(), ioe);
                }
            }
        }
        return result;
    }

    public void reconnect(){
        if (!ftpClient.isConnected()) {
            try {
                FtpUtil.setConnected();
                ftpClient.connect(_host, _port);
                ftpClient.login(_username, _password);
                ftpClient.changeWorkingDirectory(_remotePath);
            } catch (IOException e) {
                logger.error("",e);
            }
        }
    }

    public void forceReconnect() throws IOException {
        if (!ftpClient.isConnected()) {
            ftpClient.disconnect();
        }
        FtpUtil.setConnected();
        ftpClient.connect(_host, _port);
        ftpClient.login(_username, _password);
        ftpClient.changeWorkingDirectory(_remotePath);
    }

    /**
     * 强制更换目录到目标目录
     * @param pathName
     * @throws IOException
     */
    public void changeWorkingDirectory(String pathName) throws IOException {
        if (FtpUtil.ftpClient != null) {
            try {
                FtpUtil.ftpClient.changeWorkingDirectory(pathName);
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
                throw new IOException(e.getMessage());
            }
        }
    }

    /**
     * 获取当前的工作目录
     * @return
     * @throws IOException
     */
    public String getWorkingDirectory() throws IOException {
        if (FtpUtil.ftpClient != null) {
            return FtpUtil.ftpClient.printWorkingDirectory();
        }
        return null;
    }

    /**
     * 切换到指定目录(不存在就创建目录同时切换到新建的目录)
     * @param directoryId
     * @throws Exception
     */
    public void changeToRightDir(String directoryId) throws IOException {
        if (ftpClient != null) {
            String ftpDir;
            try {
                ftpDir = ftpClient.printWorkingDirectory();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
                throw new IOException(e.getMessage());
            }
            if (ftpDir == null) {
                ftpDir = "/";
            }
            String curDir;
            if (directoryId.startsWith("/")) {
                curDir = directoryId;
            } else {
                if (!ftpDir.endsWith("/")) {
                    curDir = ftpDir + FILE_SPEARATROR + directoryId;
                } else {
                    curDir = ftpDir + directoryId;
                }
            }


            boolean flag;
            try {
                flag = ftpClient.changeWorkingDirectory(curDir);
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
                throw new IOException(e.getMessage());
            }
            if (flag == false) {
                try {
                    ftpClient.makeDirectory(directoryId);
                    ftpClient.changeWorkingDirectory(curDir);
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                    throw new IOException(e.getMessage());
                }
            }
        }
    }

    /**
     * 校验连接是否正常
     * @return
     * @throws IOException
     */
    public boolean isConnected() throws IOException {
        // 检验是否连接成功
        int reply = ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)) {


            ftpClient.disconnect();
            return false;
        }
        return true;
    }

    private static void setLocalCharset(String localCharset) {
        LOCAL_CHARSET = localCharset;
    }

    private static void setConnected() throws IOException {
        FTPClient tempClient = new FTPClient();
        ftpClient = tempClient;
    }
}

 

ok,准备就绪之后,剩下 的就只有 业务层面的代码逻辑了;时间有限,不忙了补充下一篇;

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值