指尖世界

分享的乐趣

Sftp工具类

类别: 观点 更新时间: 2017-09-14

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.aspire.prm.app.iodd.common.remoteclient.RemoteClient;
import com.aspire.prm.dmplt.basic.domain.FtpConfig;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;

/**
 * name:SFTPClient
 * <p>
 * </p>
 * 
 * @author:lipeng
 * @data:2014-9-22 下午04:29:45
 * @version 1.0
 */
public class SftpClient implements RemoteClient {
    
    private static final Logger logger = Logger.getLogger(SftpClient.class);
    
    private ChannelSftp sftp;
    
    private boolean isReady = false;
    
    private FtpConfig config;
    
    /** 当前工作目录,每次关闭连接要回复到null,因为当前类是单例类 */
    private String directory = null;
    
    private Session sshSession;
    
    /**
     * 连接sftp服务器
     * 
     * @param host 主机
     * @param port 端口
     * @param username 用户名
     * @param password 密码
     * @return
     */
    public SftpClient(FtpConfig config) {
        this.config = config;
        // 设置当前工作目录
        directory = config.getRootPath();
    }
    
    private void setReady() throws Exception {
        try {
            if (!isReady) {
                JSch jsch = new JSch();
                sshSession =
                    jsch.getSession(config.getUsername(), config.getServer(), Integer.parseInt(config.getPort()));
                System.out.println("Session created.");
                sshSession.setPassword(config.getPassword());
                Properties sshConfig = new Properties();
                sshConfig.put("StrictHostKeyChecking", "no");
                sshSession.setConfig(sshConfig);
                isReady = true;
            }
            if (sshSession != null && !sshSession.isConnected()) {
                sshSession.connect();
                Channel channel = sshSession.openChannel("sftp");
                channel.connect();
                sftp = (ChannelSftp) channel;
            }
            
        } catch (Exception e) {
            this.close();
            logger.error("sftp连接服务器出错,host:" + config.getServer(), e);
            throw e;
        }
    }
    
    /**
     * 上传文件
     * 
     * @param directory 上传的目录
     * @param uploadFile 要上传的文件
     * @throws Exception 
     */
    public boolean uploadFile(String uploadFile, String remoteName) throws Exception {
        try {
            setReady();
            if (remoteName.contains("/")) {
                String remotePath = remoteName.substring(0,remoteName.lastIndexOf("/"));
                try {
                    sftp.cd(directory);
                    sftp.mkdir(remotePath);
                } catch (Exception e) {
                }
                sftp.cd(directory+"/"+remotePath);
                remoteName=remoteName.substring(remoteName.lastIndexOf("/") + 1,remoteName.length());
            }else{
                sftp.cd(directory);
            }
            File file = new File(uploadFile);
            sftp.put(new FileInputStream(file), remoteName);
            return true;
        } catch (Exception e) {
            logger.error("sftp上传文件出错,directory:" + directory, e);
            throw e;
        }
    }
    
    /**
     * 下载文件
     * 
     * @param directory 下载目录
     * @param downloadFile 下载的文件
     * @param saveFile 存在本地的路径
     * @throws Exception 
     */
    public boolean downloadFile(String downloadFile, String saveFile) throws Exception {
        try {
            setReady();
            sftp.cd(directory);
            File localFile=new File(saveFile);
            if(localFile!=null&&!localFile.exists()){
                if(localFile.getParentFile()!=null&&!localFile.getParentFile().exists()){
                    localFile.getParentFile().mkdirs();
                }
                localFile.createNewFile();
            }
            sftp.get(downloadFile, new FileOutputStream(localFile));
            return true;
        } catch (Exception e) {
            logger.error("sftp下载文件出错,directory:" + directory, e);
            throw e;
        }
    }
    
    /**
     * 删除文件
     * 
     * @param deleteFile 要删除的文件
     * @throws Exception 
     */
    public boolean removeFile(String deleteFile) throws Exception {
        try {
            setReady();
            sftp.cd(directory);
            sftp.rm(deleteFile);
            return true;
        } catch (Exception e) {
            logger.error("sftp删除文件出错,directory:" + directory, e);
            throw e;
        }
    }
    
    /**
     * 
     * 复制文件
     * @param @param src
     * @param @param dst
     * @param @return
     * @param @throws Exception     
     * @return boolean
     */
    public boolean copyFile(String src,String dst) throws Exception {
        ByteArrayInputStream bStreams =null;
        try {
            setReady();
            if (!isFileExist(src)) {
                //文件不存在直接反回.
                return false;
            }
            String parentPath=dst.substring(0,dst.lastIndexOf("/"));
            if (!this.isDirExist(parentPath)) {
                createDir(parentPath);
            }
            byte[] srcFtpFileByte = inputStreamToByte(sftp.get(src));
             bStreams = new ByteArrayInputStream(srcFtpFileByte);
            //二进制流写文件
            sftp.put(bStreams, dst);
            
            return true;
        } catch (Exception e) {
            logger.error("sftp移动文件出错,[src:" + src+",dst:"+dst+"]", e);
            throw e;
        }finally{
            if(bStreams!=null){
                bStreams.close();
            }
        }
    }
    
    /**
     * 判断远程文件是否存在
     * @param srcSftpFilePath
     * @return
     * @throws SftpException
     */
    public boolean isFileExist (String srcSftpFilePath) throws SftpException {
        boolean isExitFlag = false;
        // 文件大于等于0则存在文件
        if (getFileSize(srcSftpFilePath) >= 0) {
            isExitFlag = true;
        }
        return isExitFlag;
    }
    
    /** 
     * 得到远程文件大小
     * @param srcSftpFilePath
     * @return 返回文件大小,如返回-2 文件不存在,-1文件读取异常
     * @throws SftpException
     */
    public long getFileSize (String srcSftpFilePath) throws SftpException {
        long filesize = 0;//文件大于等于0则存在
        try {
            SftpATTRS sftpATTRS = sftp.lstat(srcSftpFilePath);
            filesize = sftpATTRS.getSize();
        } catch (Exception e) {
            filesize = -1;//获取文件大小异常
            if (e.getMessage().toLowerCase().equals("no such file")) {
                filesize = -2;//文件不存在
            }
        }
        return filesize;
    }
    /**
     * inputStream类型转换为byte类型
     * @param iStrm
     * @return
     * @throws IOException
     */
    public byte[] inputStreamToByte (InputStream iStrm) throws IOException {
        ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
        int ch;
        while ((ch = iStrm.read()) != -1) {
            bytestream.write(ch);
        }
        byte imgdata[] = bytestream.toByteArray();
        bytestream.close();
        return imgdata;
    }
    
    /**
     * 创建远程目录
     * @param sftpDirPath
     * @throws SftpException
     */
    public void createDir (String sftpDirPath) throws SftpException {
        sftp.cd("/");
        String pathArry[] = sftpDirPath.split("/");
        for (String path : pathArry) {
            if (path.equals("")) {
                continue;
            }
            if (isDirExist(path)) {
                sftp.cd(path);
            }
            else {
                //建立目录
                sftp.mkdir(path);
                //进入并设置为当前目录
                sftp.cd(path);
            }
        }
        sftp.cd(directory);
    }
    
    /**
     * 判断目录是否存在
     * @param directory
     * @return
     * @throws SftpException
     */
    public boolean isDirExist (String directory) throws SftpException {
        boolean isDirExistFlag = false;
        try {
            SftpATTRS sftpATTRS = sftp.lstat(directory);
            isDirExistFlag = true;
            return sftpATTRS.isDir();
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isDirExistFlag = false;
            }
        }
        return isDirExistFlag;
    }
    /**
     * 列出目录下的文件
     * 
     * @param directory 要列出的目录
     * @return
     * @throws SftpException
     */
    public Vector<?> listFiles() throws Exception {
        setReady();
        return sftp.ls(directory);
    }
    
    public ChannelSftp getSftp() {
        return sftp;
    }
    
    public void setSftp(ChannelSftp sftp) {
        this.sftp = sftp;
    }
    
    public void close() throws IOException {
        if (sftp != null && sftp.isConnected()) {
            sftp.disconnect();
        }
        if (sshSession != null && sshSession.isConnected()) {
            sshSession.disconnect();
        }
        isReady = false;
        logger.info("JSCH session close");
        
    }
}