使用Java实现基于SFTP协议的文件上传下载

分享一个基于第三方jar包(jsch)实现的基于SFTP协议进行文件上传下载的工具类

  • 需要注意的是:不同jsch版本默认使用的算法不一样。可以在服务器配置文件(/etc/ssh/sshd_config)根据openssh的版本决定是否需要配置支持此算法。
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Properties;
import java.util.Vector;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.linkage.utils.Conver;

/**
 * sftp工具类:主要实现基于SFTP的文件上传、下载、删除功能
 * 基于jsch.jar实现
 */
public class SFTPUtil {

    //jsch对象
    private ChannelSftp sftp;
    //jsch对象
    private Session session;
    //用户名
    private String username;
    //密码
    private String password;
    //私钥
    private String privateKey;
    //服务器ip
    private String host;
    //服务器端口
    private int port;

    //构造基于密码认证的sftp对象
    public SFTPUtil(String username, String password, String host, int port) {
        this.username = username;
        this.password = password;
        this.host = host;
        this.port = port;
    }

    //构造基于秘钥认证的sftp对象
    public SFTPUtil(String username, String host, int port, String privateKey) {
        this.username = username;
        this.host = host;
        this.port = port;
        this.privateKey = privateKey;
    }

    //默认构造器
    public SFTPUtil() {
    }

    //连接sftp服务器
    public void login() {
        try {
            JSch jsch = new JSch();
            if (StringUtils.isNotBlank(privateKey)) {
                jsch.addIdentity(privateKey);//设置私钥
            }
            session = jsch.getSession(username, host, port);
            if (StringUtils.isNotBlank(password)) {
                session.setPassword(password);//设置密码
            }
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");//不进行公钥确认
            config.put("kex", "diffie-hellman-group1-sha1");//指定jsch使用的算法,不同jsch版本默认使用的算法不一样。服务器配置文件(/etc/ssh/sshd_config)根据openssh的版本决定是否需要配置支持此算法。
            session.setConfig(config);
            session.connect();
            Channel channel = session.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
        } catch (JSchException e) {
            Conver.printStackTrace(e);
        }
    }

    //关闭连接 server
    public void logout() {
        if (sftp != null) {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
        }
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }
    
    //根据源文件路径上传附件
    public boolean upload(String srcFilePath, String remotePath, String remoteFileName){    
        return upload(new File(srcFilePath),remotePath,remoteFileName);     
    }
    
    //根据源文件File对象上传附件
    public boolean upload(File srcFile, String remotePath, String remoteFileName){  
        try {
            upload(remotePath,remoteFileName,new FileInputStream(srcFile));
        } catch (FileNotFoundException e) {
            Conver.printStackTrace(e);
            return false;
        } catch (SftpException e) {
            Conver.printStackTrace(e);
            return false;
        } finally {
            logout();
        }
        return true;
    }
    
    //通过流上传附件
    private void upload(String remotePath, String remoteFileName, InputStream input) throws SftpException {
        String[] dirs = remotePath.split("/");
        if(remotePath.startsWith("/")){
            dirs[0] = "/";
        }
        String basePath = dirs[0];
        try {
            sftp.cd(basePath);
        } catch (SftpException e) {
            sftp.mkdir(basePath);
            sftp.cd(basePath);
        }
        for(int i=1;i<dirs.length;i++){
            if(i==1 && remotePath.startsWith("/")){
                basePath += dirs[i];
            }else{              
                basePath += "/" + dirs[i];
            }
            try {
                sftp.cd(basePath);
            } catch (SftpException e) {
                sftp.mkdir(basePath);
                sftp.cd(basePath);
            }
        }           
        try{            
            sftp.put(input, remoteFileName); // 上传文件
        } finally{
            releaseIO(input);           
        }
    }
    
    
    /**
     * 
     * 下载文件
     * 
     * @param remotePath 下载目录
     * @param remoteFileName 下载的文件
     * @param localPath 存在本地的路径
     * @throws SftpException 
     * @throws FileNotFoundException 
     */
    public void download(String remoteFileName, String remotePath, String localPath) {
        FileOutputStream output = null;
        try{            
            output = new FileOutputStream(new File(localPath + File.separator + remoteFileName));
            if (StringUtils.isNotBlank(remotePath)) {
                sftp.cd(remotePath);
            }
            sftp.get(remoteFileName, output);
        } catch (FileNotFoundException e) {
        } catch (SftpException e) {
        } finally {
            releaseIO(output);
            logout();
        }
    }

    /**
     * 
     * 下载文件
     * 
     * @param directory 下载目录
     * @param downloadFile 下载的文件名
     * @return 字节数组
     */
    public byte[] download(String directory, String downloadFile) throws SftpException, IOException {
        if (directory != null && !"".equals(directory)) {
            sftp.cd(directory);
        }
        InputStream is = sftp.get(downloadFile);
        byte[] fileData = IOUtils.toByteArray(is);
        return fileData;
    }

    /**
     * 
     * 删除文件,并退出服务器
     * 
     * @param directory 要删除文件所在目录
     * @param deleteFile 要删除的文件
     */
    public void delete(String directory, String deleteFile) {
        try{
            sftp.cd(directory);
            sftp.rm(deleteFile);            
        }catch(SftpException e){
            Conver.printStackTrace(e);
        }finally{
            logout();
        }
    }
    
    /**
     * 
     * 删除文件
     * 
     * @param directory 要删除文件所在目录
     * @param deleteFile 要删除的文件
     */
    public void remove(String directory, String deleteFile) throws SftpException {
        sftp.cd(directory);
        sftp.rm(deleteFile);            
    }

    //基于sftp删除异地文件
    public static void delRemoteBySftp(String ip, String port, String user, String pwd, String remotePath, String remoteFileName) {
        SFTPUtil sftp = new SFTPUtil(user, pwd, ip, Integer.parseInt(port));
        sftp.login();
        try {
            sftp.remove(remotePath, remoteFileName);
        } catch (SftpException e) {
        }finally{           
            sftp.logout();
        }
    }
    
    /**
     * 
     * 列出目录下的文件
     * 
     * @param directory 要列出的目录
     */
    public Vector<?> listFiles(String directory) throws SftpException {
        return sftp.ls(directory);
    }
    
    //释放IO流
    public static void releaseIO(Closeable... closes){
        try{
            for(Closeable close : closes){
                if(close!=null){
                    close.close();
                }
            }
        }catch(IOException e){
        }
    }
}
上一篇:Rust这个新的语言


下一篇:springboot2.1.3配置sftp,自定义sftp连接池(转)