通过ssh实现服务器文件上传下载

通过ssh实现服务器文件上传下载

写在前面的话

之前记录过一篇使用apache的FTP开源组件实现服务器文件上传下载的方法,但是后来发现在删除的时候会有些权限问题,导致无法删除服务器上的文件。虽然在Windows上使用FileZilla Server设置读写权限后没问题,但是在服务器端还是有些不好用。

因为自己需要实现资源管理功能,除了单文件的FastDFS存储之外,一些特定资源的存储还是打算暂时存放服务器上,项目组同事说后面不会专门在服务器上开FTP服务,于是改成了sftp方式进行操作。

这个东西要怎么用

首先要去下载jsch jar包,地址是:http://www.jcraft.com/jsch/。网站上也写的很清楚:JSch is a pure Java implementation of SSH2. 这个是SSH2的纯Java实现。使用ip和端口,输入用户名密码就可以正常使用了,和Secure CRT使用方式一致。那么怎么来使用这个有用的工具呢?其实不会写也没关系,官方也给出了示例,链接:http://www.jcraft.com/jsch/examples/Shell.java,来看一眼吧:

/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/**
 * This program enables you to connect to sshd server and get the shell prompt.
 *   $ CLASSPATH=.:../build javac Shell.java 
 *   $ CLASSPATH=.:../build java Shell
 * You will be asked username, hostname and passwd. 
 * If everything works fine, you will get the shell prompt. Output may
 * be ugly because of lacks of terminal-emulation, but you can issue commands.
 *
 */
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;

public class Shell{
  public static void main(String[] arg){

    try{
      JSch jsch=new JSch();

      //jsch.setKnownHosts("/home/foo/.ssh/known_hosts");

      String host=null;
      if(arg.length>0){
        host=arg[0];
      }
      else{
        host=JOptionPane.showInputDialog("Enter username@hostname",
                                         System.getProperty("user.name")+
                                         "@localhost"); 
      }
      String user=host.substring(0, host.indexOf('@'));
      host=host.substring(host.indexOf('@')+1);

      Session session=jsch.getSession(user, host, 22);

      String passwd = JOptionPane.showInputDialog("Enter password");
      session.setPassword(passwd);

      UserInfo ui = new MyUserInfo(){
        public void showMessage(String message){
          JOptionPane.showMessageDialog(null, message);
        }
        public boolean promptYesNo(String message){
          Object[] options={ "yes", "no" };
          int foo=JOptionPane.showOptionDialog(null, 
                                               message,
                                               "Warning", 
                                               JOptionPane.DEFAULT_OPTION, 
                                               JOptionPane.WARNING_MESSAGE,
                                               null, options, options[0]);
          return foo==0;
        }

        // If password is not given before the invocation of Session#connect(),
        // implement also following methods,
        //   * UserInfo#getPassword(),
        //   * UserInfo#promptPassword(String message) and
        //   * UIKeyboardInteractive#promptKeyboardInteractive()

      };

      session.setUserInfo(ui);

      // It must not be recommended, but if you want to skip host-key check,
      // invoke following,
      // session.setConfig("StrictHostKeyChecking", "no");

      //session.connect();
      session.connect(30000);   // making a connection with timeout.

      Channel channel=session.openChannel("shell");

      // Enable agent-forwarding.
      //((ChannelShell)channel).setAgentForwarding(true);

      channel.setInputStream(System.in);
      /*
      // a hack for MS-DOS prompt on Windows.
      channel.setInputStream(new FilterInputStream(System.in){
          public int read(byte[] b, int off, int len)throws IOException{
            return in.read(b, off, (len>1024?1024:len));
          }
        });
       */

      channel.setOutputStream(System.out);

      /*
      // Choose the pty-type "vt102".
      ((ChannelShell)channel).setPtyType("vt102");
      */

      /*
      // Set environment variable "LANG" as "ja_JP.eucJP".
      ((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP");
      */

      //channel.connect();
      channel.connect(3*1000);
    }
    catch(Exception e){
      System.out.println(e);
    }
  }

  public static abstract class MyUserInfo
                          implements UserInfo, UIKeyboardInteractive{
    public String getPassword(){ return null; }
    public boolean promptYesNo(String str){ return false; }
    public String getPassphrase(){ return null; }
    public boolean promptPassphrase(String message){ return false; }
    public boolean promptPassword(String message){ return false; }
    public void showMessage(String message){ }
    public String[] promptKeyboardInteractive(String destination,
                                              String name,
                                              String instruction,
                                              String[] prompt,
                                              boolean[] echo){
      return null;
    }
  }
}

在这个代码中,我们基本上能看到需要的东西,首先我们要创建用户信息,这个主要是给认证的时候用的,只要实现 UserInfo, UIKeyboardInteractive这两个接口就好了,然后通过创建session会话,将userInfo设置进去,最后进行连接即可。

封装文件上传下载

上面是Jsch的基本使用方法,也就是些基本套路。下面我们来自己封装一下自己要使用的功能,实现文件的上传下载等一系列操作。

首先,也来创建个UserInfo:

public class MyUserInfo implements UserInfo, UIKeyboardInteractive{
    public String getPassword(){ return null; }
    public boolean promptYesNo(String str){
       return true;
    }
    public String getPassphrase(){ return null; }
    public boolean promptPassphrase(String message){ return true; }
    public boolean promptPassword(String message){
        return true;
    }
    public void showMessage(String message){
    }
    @Override
    public String[] promptKeyboardInteractive(String arg0, String arg1,
            String arg2, String[] arg3, boolean[] arg4) {
        return null;
    }
}

下面是实现类:

package com.tfxiaozi.common.utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
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.jcraft.jsch.SftpProgressMonitor;
/**
 * SSH Utils
 * @author tfxiaozi
 *
 */
public class Ssh {
    Logger logger = Logger.getLogger(this.getClass());
    private String host = "";
    private String user = "";
    private int port = 22;  
    private String password = "";
    private static final String PROTOCOL = "sftp";
    JSch jsch = new JSch();
    private Session session;
    private Channel channel;
    private ChannelSftp sftp;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public Ssh() {
    }

    public Ssh(String host, int port, String user, String password) {
        this.host = host;
        this.user = user;
        this.password = password;
        this.port = port;
    }

    /**
     * connect ssh
     * @throws JSchException
     */
    public void connect() throws JSchException {
        if (session == null) {
            session = jsch.getSession(user, host, port);
            MyUserInfo ui = new MyUserInfo();
            session.setUserInfo(ui);
            session.setPassword(password);
            session.connect();
            channel = session.openChannel(PROTOCOL);
            channel.connect();
            sftp = (ChannelSftp)channel;
        }
    }

    /**
     * disconnect ssh
     */
    public void disconnect() {
        if (session != null) {
            session.disconnect();
            session = null;
        }
    }

    /**
     * upload
     * @param localFileName
     * @param remoteFileName
     * @return
     */
    public boolean upload(String localFileName, String remoteFileName) throws Exception{
        boolean bSucc = false;
        try {
            SftpProgressMonitor monitor=new MyProgressMonitor();
            int mode=ChannelSftp.OVERWRITE;
            sftp.put(localFileName, remoteFileName, monitor, mode); 
            bSucc  = true;
        } catch(Exception e) {
            logger.error(e);
        } finally {
            if (null != channel) {
                channel.disconnect();
            }
        }
        return bSucc;
    }

    /**
     * delete file
     * @param directory
     * @param fileName
     * @return
     */
    public boolean deteleFile(String directory, String fileName) {
        boolean flag = false;
        try {
            sftp.cd(directory);
            sftp.rm(fileName);
            flag = true;
        } catch (SftpException e) {
            flag = false;
            logger.error(e);
        }
        return flag;
    }

    /**
     * delete directory
     * @param directory dir to be delete
     * @param sure be sure to delete
     * @return
     */
    public String deleteDir(String directory, boolean sure) {
        String command = "rm -rf " + directory;
        String result = execCommand(command, true);
        return result;
    }

    /**
     * compress the files and sub-dir of directory into a zip named compressName
     * @param directory the content directory to be compress
     * @param compressName the name in directory after it is compressed
     * @throws SftpException 
     * @usage ssh.compressDir("/home/tfxiaozi/webapp", "test.zip");
     */
    public void compressDir(String directory, String compressName) throws SftpException {
        String command = "cd "+ directory +"\nzip -r " + compressName + " ./" + compressName.substring(0, compressName.lastIndexOf("."));
        execCommand(command, true);
    }


    /**
     * download
     * @param localFileName
     * @param remoteFileName
     * @return
     */
    public boolean download(String localFileName, String remoteFileName) {
        boolean bSucc = false;
        Channel channel = null;
        try {
            SftpProgressMonitor monitor = new MyProgressMonitor();
            sftp.get(remoteFileName, localFileName, monitor, ChannelSftp.OVERWRITE); 
            bSucc  = true;
        } catch(Exception e) {
            logger.error(e);
        } finally {
            if (null != channel) {
                channel.disconnect();
            }
        }
        return bSucc;
    }

    /**
     * execute command
     * @param command
     * @param flag
     * @return
     */
    public String execCommand(String command, boolean flag) {
        Channel channel = null;
        InputStream in = null;
        StringBuffer sb = new StringBuffer("");
        try {
            channel = session.openChannel("exec");
            System.out.println("command:" + command);
            ((ChannelExec)channel).setCommand("export TERM=ansi && " + command);
            ((ChannelExec)channel).setErrStream(System.err);
            in = channel.getInputStream();
            channel.connect();
            if (flag) {
                byte[] tmp = new byte[10240];
                while (true) {
                    while (in.available()>0) {
                        int i = in.read(tmp, 0, 10240);
                        if(i < 0) {
                            break;
                        }
                        sb.append(new String(tmp, 0, i));
                    }
                    if (channel.isClosed()){
                        break;
                    }
                }
            }
            in.close();
        } catch(Exception e){
            logger.error(e);
        } finally {
            if (channel != null) {
                channel.disconnect();
            }
        }
        return sb.toString();
    }

    /**
     * get cpu info
     * @return
     */
    public String[] getCpuInfo() {
        Channel channel = null;
        InputStream in = null;
        StringBuffer sb = new StringBuffer("");
        try {
            channel = session.openChannel("exec");
            ((ChannelExec)channel).setCommand("export TERM=ansi && top -bn 1");//ansi一定要加
            in = channel.getInputStream();
            ((ChannelExec)channel).setErrStream(System.err);
            channel.connect();
            byte[] tmp = new byte[10240];
            while (true) {
                while (in.available()>0) {
                    int i = in.read(tmp, 0, 10240);
                    if(i < 0) {
                        break;
                    }
                    sb.append(new String(tmp, 0, i));
                }
                if (channel.isClosed()){
                    break;
                }
            }
        } catch(Exception e){
            logger.error(e);
        } finally {
            if (channel != null) {
                channel.disconnect();
            }
        }
        String buf = sb.toString();
        if (buf.indexOf("Swap") != -1) {
            buf = buf.substring(0, buf.indexOf("Swap"));
        }
        if (buf.indexOf("Cpu") != -1) {
            buf = buf.substring(buf.indexOf("Cpu"), buf.length());
        }
        buf.replaceAll(" ", "&nbsp;");
        return buf.split("\\n");
    }

    /**
     * get hard disk info
     * @return
     */
    public String getHardDiskInfo() throws Exception{
        Channel channel = null;
        InputStream in = null;
        StringBuffer sb = new StringBuffer("");
        try {
            channel = session.openChannel("exec");
            ((ChannelExec)channel).setCommand("df -lh");
            in = channel.getInputStream();
            ((ChannelExec)channel).setErrStream(System.err);
            channel.connect();

            byte[] tmp = new byte[10240];
            while (true) {
                while (in.available()>0) {
                    int i = in.read(tmp, 0, 10240);
                    if(i < 0) {
                        break;
                    }
                    sb.append(new String(tmp, 0, i));
                }
                if (channel.isClosed()){
                    break;
                }
            }
        } catch(Exception e){
            throw new RuntimeException(e);
        } finally {
            if (channel != null) {
                channel.disconnect();
            }
        }
        String buf = sb.toString();
        String[] info = buf.split("\n");
        if(info.length > 2) {//first line: Filesystem  Size  Used  Avail  Use%  Mounted on
            String tmp = "";
            for(int i=1; i< info.length; i++) {
                tmp = info[i];
                String[] tmpArr = tmp.split("%");
                if(tmpArr[1].trim().equals("/")){
                    boolean flag = true;
                    while(flag) {
                        tmp = tmp.replaceAll("  ", " ");
                        if (tmp.indexOf("  ") == -1){
                            flag = false;
                        }
                    }

                    String[] result = tmp.split(" ");
                    if(result != null && result.length == 6) {
                        buf = result[1] + " total, " + result[2] + " used, " + result[3] + " free";
                        break;
                    } else {
                        buf = "";
                    }
                }
            }
        } else {
            buf = "";
        }
        return buf;
    }

    /**
     * 返回空闲字节数
     * @return
     * @throws Exception 
     */
    public double getFreeDisk() throws Exception {
        String hardDiskInfo = getHardDiskInfo();
        if(hardDiskInfo == null || hardDiskInfo.equals("")) {
            logger.error("get free harddisk space failed.....");
            return -1;
        }
        String[] diskInfo = hardDiskInfo.replace(" ", "").split(",");
        if(diskInfo == null || diskInfo.length == 0) {
            logger.error("get free disk info failed.........");
            return -1;
        }
        String free = diskInfo[2];
        free = free.substring(0, free.indexOf("free"));
        //System.out.println("free space:" + free);
        String unit = free.substring(free.length()-1);
        //System.out.println("unit:" + unit);
        String freeSpace = free.substring(0, free.length()-1);
        double freeSpaceL = Double.parseDouble(freeSpace);
        //System.out.println("free spaceL:" + freeSpaceL);
        if(unit.equals("K")) {
            return freeSpaceL*1024;
        }else if(unit.equals("M")) {
            return freeSpaceL*1024*1024;
        } else if(unit.equals("G")) {
            return freeSpaceL*1024*1024*1024;
        } else if(unit.equals("T")) {
            return freeSpaceL*1024*1024*1024*1024;
        } else if(unit.equals("P")) {
            return freeSpaceL*1024*1024*1024*1024*1024;
        }
        return 0;
    }

    /**
     * 获取指定目录下的所有子目录及文件
     * @param directory
     * @return
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public List<String> listFiles(String directory) throws Exception {
        Vector fileList = null;
        List<String> fileNameList = new ArrayList<String>();
        fileList = sftp.ls(directory);
        Iterator it = fileList.iterator();
        while (it.hasNext()) {
            String fileName = ((ChannelSftp.LsEntry) it.next()).getFilename();
            if (fileName.startsWith(".") || fileName.startsWith("..")) {
                continue;
            }
            fileNameList.add(fileName);
        }
        return fileNameList;
    }

    public boolean mkdir(String path) {
        boolean flag = false;
        try {
            sftp.mkdir(path);
            flag = true;
        } catch (SftpException e) {
            flag = false;
        }
        return flag;
    }
}

测试一下

public static void main(String[] arg) throws Exception{
        Ssh ssh = new Ssh("10.10.10.83", 22, "test", "test");
        try {
            ssh.connect();
        } catch (JSchException e) {
            e.printStackTrace();
        }

        /*String remotePath = "/home/tfxiaozi/" + "webapp/";
        try {
            ssh.listFiles(remotePath);
        } catch (Exception e) {
            ssh.mkdir(remotePath);
        }*/


        /*boolean b = ssh.upload("d:/test.zip", "webapp/");
        System.out.println(b);*/


        //String []buf = ssh.getCpuInfo();
        //System.out.println("cpu:" + buf[0]);
        //System.out.println("memo:" + buf[1]);
        //System.out.println(ssh.getHardDiskInfo().replace(" ", ""));
        //System.out.println(ssh.getFreeDisk());


        /*List<String> list = ssh.listFiles("webapp/test");
        for(String s : list) {
            System.out.println(s);
        }*/

        /*boolean b = ssh.deteleFile("webapp", "test.zip");
        System.out.println(b);*/


        /*try {
            String s = ssh.execCommand("ls -l /home/tfxiaozi/webapp1/test", true);
            System.out.println(s);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }*/
        //ssh.sftp.setFilenameEncoding("UTF-8");

        /*try {
            String ss = ssh.execCommand("unzip /home/tfxiaozi/webapp1/test.zip -d /home/tfxiaozi/webapp1/", true);
            System.out.println(ss);
        } catch (Exception e) {
            System.out.println( e.getMessage());
        }*/


       /*String path = "/home/tfxiaozi/webapp1/test.zip";
        try {
            List<String> list = ssh.listFiles(path);
            for(String s:list) {
                System.out.println(s);
            }
            System.out.println("ok");
        } catch (Exception e) {
            System.out.println("extract failed....");
        }*/


        /*String command = "rm -rf /home/tfxiaozi/webapp1/" + "水墨国学";
        String sss = ssh.execCommand(command, true);
        System.out.println(sss);*/

        /*String findCommand = "find /home/tfxiaozi/webapp1/水墨国学 -name 'index.html'";
        String result = ssh.execCommand(findCommand, true);
        System.out.println(result);*/

        /*String path = "";
        ssh.listFiles(remotePath);*/

        /*
        ssh.deleteDir("/home/tfxiaozi/webapp1", true);
         */

        //下面这个会解压到webapp1目录,webapp1/test/xxx
        //ssh.execCommand("unzip /home/tfxiaozi/webapp1/test.zip -d /home/tfxiaozi/webapp1", true);
        //下面这个会解压到/webapp1/test目录,也是webapp1/test/test/xxx
        //ssh.execCommand("unzip /home/tfxiaozi/webapp1/test.zip -d /home/tfxiaozi/webapp1", true);

        //ssh.compressDir("/home/tfxiaozi/webapp1", "test.zip");

        //ssh.sftp.cd("/home/tfxiaozi/webapp1");
        //ssh.compressDir("/home/tfxiaozi/webapp1", "test.zip");

        /*boolean b = ssh.download("d:/temp/test.zip", "webapp/test.zip");
        System.out.println(b);*/
        //ssh.getHardDiskInfo();
        System.out.println(ssh.getFreeDisk());
        ssh.disconnect();
    }

以上就是直接使用linux方式进行操作,不过需要注意的是,对于中文文件,在解压的时候,传入的时候会有可能乱码,需要加上参数,如unzip -O cp936 test.zip -d /home/tfxiaozi/test。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值