利用ssh实现服务器文件上传下载
通过ssh实现服务器文件上传下载
写在前面的话
之前记录过一篇使用apache的FTP开源组件实现服务器文件上传下载的方法,但是后来发现在删除的时候会有些权限问题,导致无法删除服务器上的文件。虽然在Windows上使用FileZillaServer设置读写权限后没问题,但是在服务器端还是有些不好用。
因为自己需要实现资源管理功能,除了单文件的FastDFS存储之外,一些特定资源的存储还是打算暂时存放服务器上,项目组同事说后面不会专门在服务器上开FTP服务,于是改成了sftp方式进行操作。
这个东西要怎么用
首先要去下载jschjar包,地址是:http://www.jcraft.com/jsch/。网站上也写的很清楚:JSchisapureJavaimplementationofSSH2.这个是SSH2的纯Java实现。使用ip和端口,输入用户名密码就可以正常使用了,和SecureCRT使用方式一致。那么怎么来使用这个有用的工具呢?
其实不会写也没关系,官方也给出了示例,链接:http://www.jcraft.com/jsch/examples/Shell.java,来看一眼吧:
/*-*-mode:java;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /** *Thisprogramenablesyoutoconnecttosshdserverandgettheshellprompt. *$CLASSPATH=.:../buildjavacShell.java *$CLASSPATH=.:../buildjavaShell *Youwillbeaskedusername,hostnameandpasswd. *Ifeverythingworksfine,youwillgettheshellprompt.Outputmay *beuglybecauseoflacksofterminal-emulation,butyoucanissuecommands. * */ importcom.jcraft.jsch.*; importjava.awt.*; importjavax.swing.*; publicclassShell{ publicstaticvoidmain(String[]arg){ try{ JSchjsch=newJSch(); //jsch.setKnownHosts("/home/foo/.ssh/known_hosts"); Stringhost=null; if(arg.length>0){ host=arg[0]; } else{ host=JOptionPane.showInputDialog("Enterusername@hostname", System.getProperty("user.name")+ "@localhost"); } Stringuser=host.substring(0,host.indexOf('@')); host=host.substring(host.indexOf('@')+1); Sessionsession=jsch.getSession(user,host,22); Stringpasswd=JOptionPane.showInputDialog("Enterpassword"); session.setPassword(passwd); UserInfoui=newMyUserInfo(){ publicvoidshowMessage(Stringmessage){ JOptionPane.showMessageDialog(null,message); } publicbooleanpromptYesNo(Stringmessage){ Object[]options={"yes","no"}; intfoo=JOptionPane.showOptionDialog(null, message, "Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null,options,options[0]); returnfoo==0; } //IfpasswordisnotgivenbeforetheinvocationofSession#connect(), //implementalsofollowingmethods, //*UserInfo#getPassword(), //*UserInfo#promptPassword(Stringmessage)and //*UIKeyboardInteractive#promptKeyboardInteractive() }; session.setUserInfo(ui); //Itmustnotberecommended,butifyouwanttoskiphost-keycheck, //invokefollowing, //session.setConfig("StrictHostKeyChecking","no"); //session.connect(); session.connect(30000);//makingaconnectionwithtimeout. Channelchannel=session.openChannel("shell"); //Enableagent-forwarding. //((ChannelShell)channel).setAgentForwarding(true); channel.setInputStream(System.in); /* //ahackforMS-DOSpromptonWindows. channel.setInputStream(newFilterInputStream(System.in){ publicintread(byte[]b,intoff,intlen)throwsIOException{ returnin.read(b,off,(len>1024?1024:len)); } }); */ channel.setOutputStream(System.out); /* //Choosethepty-type"vt102". ((ChannelShell)channel).setPtyType("vt102"); */ /* //Setenvironmentvariable"LANG"as"ja_JP.eucJP". ((ChannelShell)channel).setEnv("LANG","ja_JP.eucJP"); */ //channel.connect(); channel.connect(3*1000); } catch(Exceptione){ System.out.println(e); } } publicstaticabstractclassMyUserInfo implementsUserInfo,UIKeyboardInteractive{ publicStringgetPassword(){returnnull;} publicbooleanpromptYesNo(Stringstr){returnfalse;} publicStringgetPassphrase(){returnnull;} publicbooleanpromptPassphrase(Stringmessage){returnfalse;} publicbooleanpromptPassword(Stringmessage){returnfalse;} publicvoidshowMessage(Stringmessage){} publicString[]promptKeyboardInteractive(Stringdestination, Stringname, Stringinstruction, String[]prompt, boolean[]echo){ returnnull; } } }
在这个代码中,我们基本上能看到需要的东西,首先我们要创建用户信息,这个主要是给认证的时候用的,只要实现UserInfo,UIKeyboardInteractive这两个接口就好了,然后通过创建session会话,将userInfo设置进去,最后进行连接即可。
封装文件上传下载
上面是Jsch的基本使用方法,也就是些基本套路。下面我们来自己封装一下自己要使用的功能,实现文件的上传下载等一系列操作。
首先,也来创建个UserInfo:
publicclassMyUserInfoimplementsUserInfo,UIKeyboardInteractive{ publicStringgetPassword(){returnnull;} publicbooleanpromptYesNo(Stringstr){ returntrue; } publicStringgetPassphrase(){returnnull;} publicbooleanpromptPassphrase(Stringmessage){returntrue;} publicbooleanpromptPassword(Stringmessage){ returntrue; } publicvoidshowMessage(Stringmessage){ } @Override publicString[]promptKeyboardInteractive(Stringarg0,Stringarg1, Stringarg2,String[]arg3,boolean[]arg4){ returnnull; } }
下面是实现类:
packagecom.tfxiaozi.common.utils; importjava.io.InputStream; importjava.util.ArrayList; importjava.util.Iterator; importjava.util.List; importjava.util.Vector; importorg.apache.log4j.Logger; importcom.jcraft.jsch.Channel; importcom.jcraft.jsch.ChannelExec; importcom.jcraft.jsch.ChannelSftp; importcom.jcraft.jsch.JSch; importcom.jcraft.jsch.JSchException; importcom.jcraft.jsch.Session; importcom.jcraft.jsch.SftpException; importcom.jcraft.jsch.SftpProgressMonitor; /** *SSHUtils *@authortfxiaozi * */ publicclassSsh{ Loggerlogger=Logger.getLogger(this.getClass()); privateStringhost=""; privateStringuser=""; privateintport=22; privateStringpassword=""; privatestaticfinalStringPROTOCOL="sftp"; JSchjsch=newJSch(); privateSessionsession; privateChannelchannel; privateChannelSftpsftp; publicStringgetHost(){ returnhost; } publicvoidsetHost(Stringhost){ this.host=host; } publicStringgetUser(){ returnuser; } publicvoidsetUser(Stringuser){ this.user=user; } publicSsh(){ } publicSsh(Stringhost,intport,Stringuser,Stringpassword){ this.host=host; this.user=user; this.password=password; this.port=port; } /** *connectssh *@throwsJSchException */ publicvoidconnect()throwsJSchException{ if(session==null){ session=jsch.getSession(user,host,port); MyUserInfoui=newMyUserInfo(); session.setUserInfo(ui); session.setPassword(password); session.connect(); channel=session.openChannel(PROTOCOL); channel.connect(); sftp=(ChannelSftp)channel; } } /** *disconnectssh */ publicvoiddisconnect(){ if(session!=null){ session.disconnect(); session=null; } } /** *upload *@paramlocalFileName *@paramremoteFileName *@return */ publicbooleanupload(StringlocalFileName,StringremoteFileName)throwsException{ booleanbSucc=false; try{ SftpProgressMonitormonitor=newMyProgressMonitor(); intmode=ChannelSftp.OVERWRITE; sftp.put(localFileName,remoteFileName,monitor,mode); bSucc=true; }catch(Exceptione){ logger.error(e); }finally{ if(null!=channel){ channel.disconnect(); } } returnbSucc; } /** *deletefile *@paramdirectory *@paramfileName *@return */ publicbooleandeteleFile(Stringdirectory,StringfileName){ booleanflag=false; try{ sftp.cd(directory); sftp.rm(fileName); flag=true; }catch(SftpExceptione){ flag=false; logger.error(e); } returnflag; } /** *deletedirectory *@paramdirectorydirtobedelete *@paramsurebesuretodelete *@return */ publicStringdeleteDir(Stringdirectory,booleansure){ Stringcommand="rm-rf"+directory; Stringresult=execCommand(command,true); returnresult; } /** *compressthefilesandsub-dirofdirectoryintoazipnamedcompressName *@paramdirectorythecontentdirectorytobecompress *@paramcompressNamethenameindirectoryafteritiscompressed *@throwsSftpException *@usagessh.compressDir("/home/tfxiaozi/webapp","test.zip"); */ publicvoidcompressDir(Stringdirectory,StringcompressName)throwsSftpException{ Stringcommand="cd"+directory+"\nzip-r"+compressName+"./"+compressName.substring(0,compressName.lastIndexOf(".")); execCommand(command,true); } /** *download *@paramlocalFileName *@paramremoteFileName *@return */ publicbooleandownload(StringlocalFileName,StringremoteFileName){ booleanbSucc=false; Channelchannel=null; try{ SftpProgressMonitormonitor=newMyProgressMonitor(); sftp.get(remoteFileName,localFileName,monitor,ChannelSftp.OVERWRITE); bSucc=true; }catch(Exceptione){ logger.error(e); }finally{ if(null!=channel){ channel.disconnect(); } } returnbSucc; } /** *executecommand *@paramcommand *@paramflag *@return */ publicStringexecCommand(Stringcommand,booleanflag){ Channelchannel=null; InputStreamin=null; StringBuffersb=newStringBuffer(""); try{ channel=session.openChannel("exec"); System.out.println("command:"+command); ((ChannelExec)channel).setCommand("exportTERM=ansi&&"+command); ((ChannelExec)channel).setErrStream(System.err); in=channel.getInputStream(); channel.connect(); if(flag){ byte[]tmp=newbyte[10240]; while(true){ while(in.available()>0){ inti=in.read(tmp,0,10240); if(i<0){ break; } sb.append(newString(tmp,0,i)); } if(channel.isClosed()){ break; } } } in.close(); }catch(Exceptione){ logger.error(e); }finally{ if(channel!=null){ channel.disconnect(); } } returnsb.toString(); } /** *getcpuinfo *@return */ publicString[]getCpuInfo(){ Channelchannel=null; InputStreamin=null; StringBuffersb=newStringBuffer(""); try{ channel=session.openChannel("exec"); ((ChannelExec)channel).setCommand("exportTERM=ansi&&top-bn1");//ansi一定要加 in=channel.getInputStream(); ((ChannelExec)channel).setErrStream(System.err); channel.connect(); byte[]tmp=newbyte[10240]; while(true){ while(in.available()>0){ inti=in.read(tmp,0,10240); if(i<0){ break; } sb.append(newString(tmp,0,i)); } if(channel.isClosed()){ break; } } }catch(Exceptione){ logger.error(e); }finally{ if(channel!=null){ channel.disconnect(); } } Stringbuf=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(""," "); returnbuf.split("\\n"); } /** *getharddiskinfo *@return */ publicStringgetHardDiskInfo()throwsException{ Channelchannel=null; InputStreamin=null; StringBuffersb=newStringBuffer(""); try{ channel=session.openChannel("exec"); ((ChannelExec)channel).setCommand("df-lh"); in=channel.getInputStream(); ((ChannelExec)channel).setErrStream(System.err); channel.connect(); byte[]tmp=newbyte[10240]; while(true){ while(in.available()>0){ inti=in.read(tmp,0,10240); if(i<0){ break; } sb.append(newString(tmp,0,i)); } if(channel.isClosed()){ break; } } }catch(Exceptione){ thrownewRuntimeException(e); }finally{ if(channel!=null){ channel.disconnect(); } } Stringbuf=sb.toString(); String[]info=buf.split("\n"); if(info.length>2){//firstline:FilesystemSizeUsedAvailUse%Mountedon Stringtmp=""; for(inti=1;i<info.length;i++){ tmp=info[i]; String[]tmpArr=tmp.split("%"); if(tmpArr[1].trim().equals("/")){ booleanflag=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=""; } returnbuf; } /** *返回空闲字节数 *@return *@throwsException */ publicdoublegetFreeDisk()throwsException{ StringhardDiskInfo=getHardDiskInfo(); if(hardDiskInfo==null||hardDiskInfo.equals("")){ logger.error("getfreeharddiskspacefailed....."); return-1; } String[]diskInfo=hardDiskInfo.replace("","").split(","); if(diskInfo==null||diskInfo.length==0){ logger.error("getfreediskinfofailed........."); return-1; } Stringfree=diskInfo[2]; free=free.substring(0,free.indexOf("free")); //System.out.println("freespace:"+free); Stringunit=free.substring(free.length()-1); //System.out.println("unit:"+unit); StringfreeSpace=free.substring(0,free.length()-1); doublefreeSpaceL=Double.parseDouble(freeSpace); //System.out.println("freespaceL:"+freeSpaceL); if(unit.equals("K")){ returnfreeSpaceL*1024; }elseif(unit.equals("M")){ returnfreeSpaceL*1024*1024; }elseif(unit.equals("G")){ returnfreeSpaceL*1024*1024*1024; }elseif(unit.equals("T")){ returnfreeSpaceL*1024*1024*1024*1024; }elseif(unit.equals("P")){ returnfreeSpaceL*1024*1024*1024*1024*1024; } return0; } /** *获取指定目录下的所有子目录及文件 *@paramdirectory *@return *@throwsException */ @SuppressWarnings("rawtypes") publicList<String>listFiles(Stringdirectory)throwsException{ VectorfileList=null; List<String>fileNameList=newArrayList<String>(); fileList=sftp.ls(directory); Iteratorit=fileList.iterator(); while(it.hasNext()){ StringfileName=((ChannelSftp.LsEntry)it.next()).getFilename(); if(fileName.startsWith(".")||fileName.startsWith("..")){ continue; } fileNameList.add(fileName); } returnfileNameList; } publicbooleanmkdir(Stringpath){ booleanflag=false; try{ sftp.mkdir(path); flag=true; }catch(SftpExceptione){ flag=false; } returnflag; } }
测试一下
publicstaticvoidmain(String[]arg)throwsException{ Sshssh=newSsh("10.10.10.83",22,"test","test"); try{ ssh.connect(); }catch(JSchExceptione){ e.printStackTrace(); } /*StringremotePath="/home/tfxiaozi/"+"webapp/"; try{ ssh.listFiles(remotePath); }catch(Exceptione){ ssh.mkdir(remotePath); }*/ /*booleanb=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(Strings:list){ System.out.println(s); }*/ /*booleanb=ssh.deteleFile("webapp","test.zip"); System.out.println(b);*/ /*try{ Strings=ssh.execCommand("ls-l/home/tfxiaozi/webapp1/test",true); System.out.println(s); }catch(Exceptione){ System.out.println(e.getMessage()); }*/ //ssh.sftp.setFilenameEncoding("UTF-8"); /*try{ Stringss=ssh.execCommand("unzip/home/tfxiaozi/webapp1/test.zip-d/home/tfxiaozi/webapp1/",true); System.out.println(ss); }catch(Exceptione){ System.out.println(e.getMessage()); }*/ /*Stringpath="/home/tfxiaozi/webapp1/test.zip"; try{ List<String>list=ssh.listFiles(path); for(Strings:list){ System.out.println(s); } System.out.println("ok"); }catch(Exceptione){ System.out.println("extractfailed...."); }*/ /*Stringcommand="rm-rf/home/tfxiaozi/webapp1/"+"水墨国学"; Stringsss=ssh.execCommand(command,true); System.out.println(sss);*/ /*StringfindCommand="find/home/tfxiaozi/webapp1/水墨国学-name'index.html'"; Stringresult=ssh.execCommand(findCommand,true); System.out.println(result);*/ /*Stringpath=""; 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"); /*booleanb=ssh.download("d:/temp/test.zip","webapp/test.zip"); System.out.println(b);*/ //ssh.getHardDiskInfo(); System.out.println(ssh.getFreeDisk()); ssh.disconnect(); }
以上就是直接使用linux方式进行操作,不过需要注意的是,对于中文文件,在解压的时候,传入的时候会有可能乱码,需要加上参数,如unzip-Ocp936test.zip-d/home/tfxiaozi/test。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。