欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

利用ssh实现服务器文件上传下载

程序员文章站 2024-03-13 16:04:21
通过ssh实现服务器文件上传下载 写在前面的话 之前记录过一篇使用apache的ftp开源组件实现服务器文件上传下载的方法,但是后来发现在删除的时候会有些权限问题,导致...

通过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(" ", " ");
  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。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。