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

作者:ForeverSunshine 时间:2021-10-16 09:28:47 

通过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();
}

标签:ssh,上传,下载
0
投稿

猜你喜欢

  • springboot 定时任务@Scheduled实现解析

    2023-11-10 16:18:24
  • 关于springboot配置文件密文解密方式

    2023-11-09 04:21:24
  • springcloud配置ssh的问题及解决方法

    2023-11-03 15:48:11
  • Hadoop源码分析六启动文件namenode原理详解

    2021-08-20 01:03:55
  • Java数组索引异常产生及解决方案

    2023-11-05 16:52:27
  • SpringMVC数据输出相关知识总结

    2022-04-06 10:35:06
  • java,android,MD5加密算法的实现代码(16位,32位)

    2022-07-12 20:40:10
  • SpringBoot深入分析讲解监听器模式上

    2022-06-25 21:04:04
  • Java使用ArrayList实现扑克牌的示例代码

    2021-10-29 15:17:17
  • JAVA NIO实现简单聊天室功能

    2023-05-01 10:32:49
  • Java实现简单的分页功能

    2021-06-02 01:32:48
  • Java 设计模式中的命令模式详情

    2023-11-15 23:25:33
  • Spring Boot2如何构建可部署的war包

    2023-11-29 06:40:59
  • MyBatis使用动态SQL标签的小陷阱

    2023-09-11 04:42:57
  • 详解Struts2动态方法调用

    2022-10-18 11:19:25
  • Mybatis-Spring源码分析图解

    2023-07-18 13:35:07
  • IDEA Error:java:无效的源发行版:13的解决过程

    2023-11-25 10:07:19
  • Java实现动态获取文件的绝对路径

    2022-12-19 00:34:14
  • IntelliJ IDEA快速创建getter和setter方法

    2023-06-04 00:44:46
  • 详解Java设计模式——命令模式

    2023-11-23 05:00:07
  • asp之家 软件编程 m.aspxhome.com