package com.tzy.framework.pay.util.sftp;


import com.jcraft.jsch.*;

import java.io.*;

public class SFtpClient {

    private String ftpHost;
    private int ftpPort;
    private String uploadRemotePath; //上传到的服务器目录
    private String downloadRemotePath;//从服务器哪个目录下载
    private String userName;
    private String password;
    private int timeOut = 30000;

    private Session session = null;
    private ChannelSftp channel = null;

    public SFtpClient() {
        super();
    }

    public SFtpClient(String ftpHost, int ftpPort, String uploadRemotePath, String downloadRemotePath, String userName, String password) {
        super();
        this.ftpHost = ftpHost;
        this.ftpPort = ftpPort<=0? 22:ftpPort ;
        this.uploadRemotePath = uploadRemotePath;
        this.downloadRemotePath = downloadRemotePath;
        this.userName = userName;
        this.password = password;
    }

    /**
     * 利用JSch包通过SFTP链接
     * @throws JSchException
     */
    public void connect() throws JSchException {
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(userName, ftpHost, ftpPort);
            // 如果服务器连接不上，则抛出异常
            if (session == null) {
                throw new JSchException("session is null");
            }
            session.setPassword(password);// 设置密码
            session.setConfig("StrictHostKeyChecking", "no");// 设置第一次登陆的时候提示，可选值：(ask
            // | yes | no)
            //设置登陆超时时间
            session.connect(timeOut);

            channel = (ChannelSftp) session.openChannel("sftp");// 创建sftp通信通道
            channel.connect(1000);

        } catch (JSchException e) {
            e.printStackTrace();
            session.disconnect();
            channel.disconnect();
            throw e;
        }

    }

    /**
     * 上传文件
     * @param localFile 本地上传文件
     * @throws SftpException
     * @throws IOException
     */
    public void uploadFile(File localFile) throws SftpException, IOException {

        String fullremoteFileName = this.uploadRemotePath + localFile.getName();
        this.uploadFile(localFile, fullremoteFileName);
    }

    public void uploadFile(File localFile, String fullremoteFileName) throws  IOException, SftpException {
        OutputStream outstream = null;
        InputStream instream = null;

        try {
            // 判断是否是文件夹
            if (!isPath(fullremoteFileName.substring(0, fullremoteFileName.lastIndexOf("/")))) {
                createPath(fullremoteFileName.substring(0, fullremoteFileName.lastIndexOf("/")));
            }
            outstream = channel.put(fullremoteFileName);
            instream = new FileInputStream(localFile);
            byte b[] = new byte[1024];
            int n;
            while ((n = instream.read(b)) != -1) {
                outstream.write(b, 0, n);
            }
            outstream.flush();

        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                instream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                outstream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    /**
     * 下载文件
     * @param remeotFileName
     * @param downloadLocalFile 下载到本地的文件
     * @throws SftpException
     * @throws IOException
     */
    public void downloadFile(String remeotFileName, File downloadLocalFile) throws SftpException, IOException {

        String fullremoteDownloadFileName = this.downloadRemotePath + remeotFileName;
        this.downloadFile(downloadLocalFile, fullremoteDownloadFileName);
    }

    public void downloadFile(File downloadLocalFile, String fullremoteDownloadFileName) throws  IOException, SftpException {
        OutputStream outstream = null;
        InputStream instream = null;

        try {

            instream = channel.get(fullremoteDownloadFileName);
            outstream = new FileOutputStream(downloadLocalFile);

            byte b[] = new byte[1024];
            int n;
            while ((n = instream.read(b)) != -1) {
                outstream.write(b, 0, n);
            }
            outstream.flush();

        } catch (IOException e) {
            throw e;
        }  catch (SftpException e) {
            throw e;
        }
        finally {
            try {
                if(instream!=null){
                    instream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(outstream != null){
                    outstream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    public void uploadFile(String localPath,String localFileName) throws SftpException, IOException {
        this.uploadFile(localPath,localFileName, localFileName);

    }

    public void uploadFile(String localPath,String localFileName, String remoteFileName) throws SftpException, IOException {
        String fullLocalFileName = localPath + localFileName;
        String fullremoteFileName =this.uploadRemotePath + remoteFileName;
        uploadFile(new File(fullLocalFileName), fullremoteFileName);
    }

    public void disconnect() {
        session.disconnect();
        channel.disconnect();
    }

    public void createPath(String remotePath) {
        String[] paths = remotePath.split("/");
        String currentPath;
        if (remotePath.startsWith("/")) {
            currentPath = "/";
        } else {
            currentPath = "";
        }

        for (String path : paths) {
            if ("".equals(path)) {
                continue;
            }
            currentPath += path + "/";
            try {
                channel.mkdir(currentPath);
            } catch (SftpException e) {
//                e.printStackTrace();
                // throw e;
            }
        }
    }

    public boolean isPath(String remotePath) {
        // 判断是否是文件夹
        try {
            channel.cd(channel.getHome());
            channel.cd(remotePath);
            channel.cd(channel.getHome());
            return true;
        } catch (SftpException e1) {
            // e1.printStackTrace();
            return false;
        }
    }

}
