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 **
* * @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"); }}