利用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(" ", " "); 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。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。