利用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(" ", " ");
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();
}