引入jar包
<dependency>
<groupId>cn.liberfree</groupId>
<artifactId>sftp</artifactId>
<version>1.1-RELEASE</version>
<type>pom</type>
</dependency>
SFTP的使用:
1.项目中需要引入jar包,下载地址:https://sourceforge.net/projects/jsch/files/jsch.jar/
2.需要下载SFTP服务器,下载地址:http://www.freesshd.com/?ctt=download
服务器的配置参考:http://www.cnblogs.com/zxx-813/p/7353806.html、http://jingyan.baidu.com/article/f7ff0bfc1ebd322e27bb1344.html
3.java代码(基于SFTP上传、下载文件(单个以及批量)):
ChannelSftp使用api:http://epaul.github.io/jsch-documentation/javadoc/index.html?com/jcraft/jsch/ChannelSftp.html
java 中使用
package test.sftp; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Vector; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.ChannelSftp.LsEntry; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.SftpATTRS; import com.jcraft.jsch.SftpException; public class Test2 { private static ChannelSftp sftp = null; private static String host = "127.0.0.1"; private static int port = 22; private static String username = "root"; private static String password = "root"; private static Session sshSession = null; /** * main方法 * @param args */ public static void main(String[] args) { ChannelSftp channelSftp = connect(host, port, username, password); System.out.println(channelSftp); sftp = channelSftp; /** * 上传单个文件 * @param remotePath:远程保存目录 * @param remoteFileName:保存文件名 * @param localPath:本地上传目录(以路径符号结束) * @param localFileName:上传的文件名 * @return */ /*String remotePath = "/test1/"; //远程保存目录 String remoteFileName = "test.rar"; //保存文件名 String localPath = "C:\Users\lyc\Desktop\"; //本地上传目录(以路径符号结束) String localFileName = "msftpsrvr.rar"; //reservation3.sql //上传的文件名 uploadFile(remotePath,remoteFileName,localPath,localFileName);*/ /** * 下载单个文件 * @param directory:下载目录 * @param downloadFile:下载的文件 * @param saveFile:存在本地的路径 * @param sftp */ /*String directory = "/test/"; //下载目录 String downloadFile = "test.sql"; //下载的文件 String saveFile = "D:\"; //存在本地的路径 download(directory,downloadFile,saveFile,sftp);*/ /** * 批量上传文件 * @param remotePath:远程保存目录 * @param localPath:本地上传目录(以路径符号结束) * @param del:上传后是否删除本地文件 * @return */ /*String remotePath = "/test/"; String localPath = "C:/Users/lyc/Desktop/aa/"; boolean del = false; bacthUploadFile(remotePath,localPath,del);*/ /** * 批量下载文件 * @param remotPath:远程下载目录(以路径符号结束,可以为相对路径eg:/assess/sftp/jiesuan_2/2014/) * @param localPath:本地保存目录(以路径符号结束,D:Duanshasftp) * @param fileFormat:下载文件格式(以特定字符开头,为空不做检验) * @param fileEndFormat:下载文件格式(文件格式) * @param del:下载后是否删除sftp文件 * @return */ String remotePath = "/test/"; String localPath = "C:/Users/lyc/Desktop/aa/"; String fileFormat = ""; //下载特定字符开头的文件 String fileEndFormat = "x"; //下载某一种格式的文件(下载特定字符结尾的文件) boolean del = false; batchDownLoadFile(remotePath,localPath,fileFormat,fileEndFormat,del); } /** * 链接sftp服务器 * @param host 服务器地址 * @param port 服务器端口 * @param username 登录用户名 * @param password 登录密码 * @return */ public static ChannelSftp connect(String host,int port,String username,String password){ ChannelSftp sftp = null; JSch jsch = new JSch(); try { sshSession = jsch.getSession(username, host, port); System.out.println("创建session!"); sshSession.setPassword(password); Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking", "no"); sshSession.setConfig(sshConfig); sshSession.connect(); System.out.println("session链接"); Channel channel = sshSession.openChannel("sftp"); channel.connect(); sftp = (ChannelSftp)channel; System.out.println("成功链接到"+host+"."); } catch (JSchException e) { // TODO Auto-generated catch block e.printStackTrace(); } return sftp; } /** * 上传单个文件 * @param remotePath:远程保存目录 * @param remoteFileName:保存文件名 * @param localPath:本地上传目录(以路径符号结束) * @param localFileName:上传的文件名 * @return */ public static boolean uploadFile(String remotePath, String remoteFileName,String localPath, String localFileName){ FileInputStream in = null; try { createDir(remotePath); //远程保存目录 File file = new File(localPath + localFileName); //本地上传目录(以路径符号结束) in = new FileInputStream(file); sftp.put(in, remoteFileName); //远程文件名 return true; }catch (FileNotFoundException e){ e.printStackTrace(); }catch (SftpException e){ e.printStackTrace(); } finally { if (in != null){ try{ in.close(); }catch (IOException e){ e.printStackTrace(); } } } return false; } /** * 创建目录 * @param createpath 远程保存目录 * @return */ public static boolean createDir(String createpath) { try { if (isDirExist(createpath)){ //文件存在 sftp.cd(createpath); //cd()更改当前远程目录 return true; } String pathArry[] = createpath.split("/"); StringBuffer filePath = new StringBuffer("/"); for (String path : pathArry){ if (path.equals("")){ continue; } filePath.append(path + "/"); if (isDirExist(filePath.toString())){ sftp.cd(filePath.toString()); } else{ // 建立目录 sftp.mkdir(filePath.toString()); //mkdir()创建一个新的远程目录 // 进入并设置为当前目录 sftp.cd(filePath.toString()); } } sftp.cd(createpath); return true; } catch (SftpException e){ e.printStackTrace(); } return false; } /** * 判断目录是否存在 * @param directory * @return */ public static boolean isDirExist(String directory){ boolean isDirExistFlag = false; try{ SftpATTRS sftpATTRS = sftp.lstat(directory); //lstat()检索文件或目录的文件属性 isDirExistFlag = true; System.out.println(sftpATTRS.isDir()); return sftpATTRS.isDir(); //isDir()检查此文件是否为目录 }catch (Exception e){ if (e.getMessage().toLowerCase().equals("no such file")){ isDirExistFlag = false; } } return isDirExistFlag; } /** * 下载单个文件 * @param directory 下载目录 * @param downloadFile 下载的文件 * @param saveFile 存在本地的路径 * @param sftp */ public static void download(String directory, String downloadFile, String saveFile, ChannelSftp sftp) { try { sftp.cd(directory); //下载目录 sftp.get(downloadFile,saveFile); //下载的文件 存在本地的路径 }catch (Exception e){ e.printStackTrace(); } } /** * 批量上传文件 * @param remotePath:远程保存目录 * @param localPath:本地上传目录(以路径符号结束) * @param del:上传后是否删除本地文件 * @return */ public static boolean bacthUploadFile(String remotePath, String localPath, boolean del) { try { /*connect();*/ File file = new File(localPath); File[] files = file.listFiles(); for (int i = 0; i < files.length; i++){ if (files[i].isFile() && files[i].getName().indexOf("bak") == -1){ if (uploadFile(remotePath, files[i].getName(), localPath, files[i].getName()) && del){ //上传文件 deleteFile(localPath + files[i].getName()); //上传后删除本地文件 } } } /*if (log.isInfoEnabled()) { log.info("upload file is success:remotePath=" + remotePath + "and localPath=" + localPath + ",file size is " + files.length); }*/ return true; }catch (Exception e){ e.printStackTrace(); }finally{ disconnect(); } return false; } /** * 删除本地文件 * @param filePath * @return */ public static boolean deleteFile(String filePath){ File file = new File(filePath); if (!file.exists()){ return false; } if (!file.isFile()){ return false; } boolean rs = file.delete(); /*if (rs && log.isInfoEnabled()) { log.info("delete file success from local."); }*/ return rs; } /** * 关闭连接 */ public static void disconnect(){ if (sftp != null){ if (sftp.isConnected()){ sftp.disconnect(); /*if (log.isInfoEnabled()) { log.info("sftp is closed already"); }*/ } } if (sshSession != null){ if (sshSession.isConnected()){ sshSession.disconnect(); /*if (log.isInfoEnabled()) { log.info("sshSession is closed already"); }*/ } } } /** * 批量下载文件 * @param remotPath:远程下载目录(以路径符号结束,可以为相对路径eg:/assess/sftp/jiesuan_2/2014/) * @param localPath:本地保存目录(以路径符号结束,D:Duanshasftp) * @param fileFormat:下载文件格式(以特定字符开头,为空不做检验) * @param fileEndFormat:下载文件格式(文件格式) * @param del:下载后是否删除sftp文件 * @return */ @SuppressWarnings("rawtypes") public static List<String> batchDownLoadFile(String remotePath, String localPath, String fileFormat, String fileEndFormat, boolean del) { List<String> filenames = new ArrayList<String>(); try { // connect(); //Vector v = listFiles(remotePath); Vector v = sftp.ls(remotePath); //lstat(String path):列出远程目录的内容 // sftp.cd(remotePath); if (v.size() > 0) { System.out.println("本次处理文件个数不为零,开始下载...fileSize=" + v.size()); Iterator it = v.iterator(); while (it.hasNext()) { LsEntry entry = (LsEntry) it.next(); String filename = entry.getFilename(); SftpATTRS attrs = entry.getAttrs(); if (!attrs.isDir()) { boolean flag = false; String localFileName = localPath + filename; fileFormat = fileFormat == null ? "" : fileFormat .trim(); fileEndFormat = fileEndFormat == null ? "" : fileEndFormat.trim(); // 三种情况 if (fileFormat.length() > 0 && fileEndFormat.length() > 0) { if (filename.startsWith(fileFormat) && filename.endsWith(fileEndFormat)) { flag = downloadFile(remotePath, filename,localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } else if (fileFormat.length() > 0 && "".equals(fileEndFormat)) { if (filename.startsWith(fileFormat)) { flag = downloadFile(remotePath, filename, localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } else if (fileEndFormat.length() > 0 && "".equals(fileFormat)) { if (filename.endsWith(fileEndFormat)) { flag = downloadFile(remotePath, filename,localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } else { flag = downloadFile(remotePath, filename,localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } } } /*if (log.isInfoEnabled()) { log.info("download file is success:remotePath=" + remotePath + "and localPath=" + localPath + ",file size is" + v.size()); }*/ } catch (SftpException e) { e.printStackTrace(); } finally { // this.disconnect(); } return filenames; } /** * 下载单个文件 * @param remotPath:远程下载目录(以路径符号结束) * @param remoteFileName:下载文件名 * @param localPath:本地保存目录(以路径符号结束) * @param localFileName:保存文件名 * @return */ public static boolean downloadFile(String remotePath, String remoteFileName,String localPath, String localFileName) { FileOutputStream fieloutput = null; try { // sftp.cd(remotePath); File file = new File(localPath + localFileName); // mkdirs(localPath + localFileName); fieloutput = new FileOutputStream(file); sftp.get(remotePath + remoteFileName, fieloutput); /*if (log.isInfoEnabled()) { log.info("===DownloadFile:" + remoteFileName + " success from sftp."); }*/ return true; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (SftpException e) { e.printStackTrace(); } finally { if (null != fieloutput) { try { fieloutput.close(); } catch (IOException e) { e.printStackTrace(); } } } return false; } /** * 删除stfp文件 * @param directory:要删除文件所在目录 * @param deleteFile:要删除的文件 * @param sftp */ public static void deleteSFTP(String directory, String deleteFile) { try { // sftp.cd(directory); sftp.rm(directory + deleteFile); /*if (log.isInfoEnabled()) { log.info("delete file success from sftp."); }*/ } catch (Exception e) { e.printStackTrace(); } } /** * 列出目录下的文件 * * @param directory:要列出的目录 * @param sftp * @return * @throws SftpException */ /*@SuppressWarnings("rawtypes") public static Vector listFiles(String directory) throws SftpException { return sftp.ls(directory); }*/ }
使用2: 涉及密钥下载文件
package com.qing.niu.communication.sftp; import com.jcraft.jsch.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Assert; import java.io.*; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * <p> * Sftp工具类 * </p> * * @author huqingniu * @version 1.0.0 * @date 2018/12/24 */ public class SftpTool { public static final Logger logger = LoggerFactory.getLogger(SftpTool.class); private String host; private String username; private int port; public SftpTool(String host, String username, int port){ this.host = host; this.username = username; this.port = port; } /** * 登陆sftp * * @param authTypeMode 认证方式 * @return 登陆信息 */ public Map<String,Object> loginIn(AuthTypeMode authTypeMode){ //解决JSch日志打印问题 JSch.setLogger(new SettleJschLogPrint()); try { ChannelSftp sftp = null; Session session = null; JSch jsch = new JSch(); logger.info("获取SFTP服务器连接username:{},host:{},port:{}",username,host,port); session = jsch.getSession(username,host,port); logger.info("连接成功建立"); if (AuthTypeEnum.RSA.getCode().equals(authTypeMode.getAuthType())){ jsch.addIdentity(authTypeMode.getAuthValue(),""); }else { session.setPassword(authTypeMode.getAuthValue()); } Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking","no"); sshConfig.put("PreferredAuthentications","publickey,gssapi-with-mic,keyboard-interactive,password"); session.setConfig(sshConfig); session.connect(); logger.info("用户" + username + "成功登陆"); Channel channel = session.openChannel("sftp"); channel.connect(); sftp = (ChannelSftp) channel; HashMap<String,Object> loginInfo = new HashMap<>(); loginInfo.put("sftp",sftp); loginInfo.put("session",session); return loginInfo; } catch (JSchException e) { throw new RuntimeException("user login SFTP server occur exception:" + e); } } /** * 退出登陆 * * @param sftp sftp对象 * @param session session对象 */ public void loginOut(ChannelSftp sftp, Session session){ try { if(null != sftp && sftp.isConnected()){ sftp.disconnect(); } if (null != session && session.isConnected()){ session.disconnect(); } } catch (Exception e) { logger.warn("用户退出SFTP服务器出现异常:" + e); } } /** * 下载文件 * * @param downloadFilePath 要下载的文件所在绝对路径 * @param downloadFileName 要下载的文件名(sftp服务器上的文件名) * @param saveFile 文件存放位置(文件所在绝对路径) * @param authTypeMode 用户认证方式 */ public void download(String downloadFilePath, String downloadFileName, File saveFile, AuthTypeMode authTypeMode) throws Exception{ Assert.notNull(downloadFilePath,"download file absolute path is not null"); Assert.notNull(downloadFileName,"download file is not null"); Assert.notNull(saveFile,"save file location is not null"); Assert.notNull(authTypeMode,"auth type way is not null"); OutputStream outputStream = null; ChannelSftp sftp = null; Session session = null; try { Map<String,Object> loginInfo = loginIn(authTypeMode); sftp = (ChannelSftp) loginInfo.get("sftp"); session = (Session) loginInfo.get("session"); logger.info("待下载文件地址为:" + downloadFilePath + ",文件名为:" + downloadFileName + ",认证方式:" + authTypeMode.getAuthValue()); sftp.cd(downloadFilePath); sftp.ls(downloadFileName); outputStream = new FileOutputStream(saveFile); sftp.get(downloadFileName,outputStream); logger.info("文件下载完成!"); } finally { if (null != outputStream){ outputStream.close(); } loginOut(sftp,session); } } /** * 上传文件 * * @param uploadPath 上传SFTP完整路径 * @param uploadFile 上传文件(完整路径) * @param authTypeMode 认证方式 */ public void upload(String uploadPath, String uploadFile, AuthTypeMode authTypeMode) throws Exception{ Assert.notNull(uploadPath,"upload path is not null"); Assert.notNull(uploadFile,"upload file is not null"); Assert.notNull(authTypeMode,"auth type way is not null"); InputStream inputStream = null; ChannelSftp sftp = null; Session session = null; try { Map<String,Object> loginInfo = loginIn(authTypeMode); sftp = (ChannelSftp) loginInfo.get("sftp"); session = (Session) loginInfo.get("session"); logger.info("待上传文件为:" + uploadFile + ",上传SFTP服务器路径:" + uploadPath + ",认证方式:" + authTypeMode.getAuthValue()); File file = new File(uploadFile); inputStream = new FileInputStream(file); try { sftp.cd(uploadPath); } catch (SftpException e) { logger.error("SFTP器服务存放文件路径不存在"); throw new RuntimeException("upload path is not exist"); } sftp.put(inputStream,file.getName()); logger.info("上传文件成功!"); } finally { if (null != inputStream){ inputStream.close(); } loginOut(sftp,session); } } /** * authType = PASSWORD,authValue = password * authType = rsa,authValue = rsa文件路径 */ class AuthTypeMode{ private String authType; private String authValue; AuthTypeMode(String authType, String authValue){ this.authType = authType; this.authValue = authValue; } String getAuthType(){ return authType; } String getAuthValue(){ return authValue; } } /** * 在slf4j日志框架里打印JSch日志 */ class SettleJschLogPrint implements com.jcraft.jsch.Logger{ @Override public boolean isEnabled(int i) { return true; } @Override public void log(int i, String s) { logger.info(s); } } enum AuthTypeEnum { PASSWORD("PASSWORD","密码认证"), RSA("RSA","rsa密钥认证"); private String code; private String desc; AuthTypeEnum(String code, String desc){ this.code = code; this.desc = desc; } public String getCode(){ return this.code; } } public static void main(String[] args) throws Exception{ //密码认证方式 SftpTool sftpTool = new SftpTool("192.168.79.151","albert",22); //下载文件 File saveFile = new File("/data/sftp/verifyfile_01.txt"); sftpTool.download("/verifyfile","verifyfile_01.csv",saveFile,sftpTool.new AuthTypeMode(AuthTypeEnum.PASSWORD.getCode(),"alan123456")); //上传文件 sftpTool.upload("/verifyfile","/data/sftp/verifyfile_01.txt",sftpTool.new AuthTypeMode(AuthTypeEnum.PASSWORD.getCode(),"alan123456")); //密钥认证方式下载文件 SftpTool sftpToolTwo = new SftpTool("192.168.79.151","qingniu",22); File saveFileTwo = new File("/data/sftp/verifyfile_01.txt"); sftpToolTwo.download("/verifyfile","verifyfile_01.csv",saveFileTwo,sftpToolTwo.new AuthTypeMode(AuthTypeEnum.RSA.getCode(),"/data/rsa/id_rsa_qingniu")); //密钥认证方式上传文件( 上传会失败Permission denied,因为qingniu这个用户没有写的权限 ) sftpToolTwo.upload("/verifyfile","/data/sftp/verifyfile_01.txt",sftpToolTwo.new AuthTypeMode(AuthTypeEnum.RSA.getCode(),"/data/rsa/id_rsa_qingniu")); } }
原文链接: https://www.cnblogs.com/super-chao/p/7797944.html
https://blog.csdn.net/alan_gui/java/article/details/85220010