首页 > 编程 > Java > 正文

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

2019-11-26 13:50:05
字体:
来源:转载
供稿:网友

通过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。

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表