<需求:以sftp方式连接A服务器下载指定文件,再上传到B服务器中>
1、参数
private Session session = null;
/** Channel */
private ChannelSftp channel = null;
/** SFTP服务器IP地址 */
private String host;
/** SFTP服务器端口 */
private int port;
/** 连接超时时间,单位毫秒 */
private int timeout;
/** 用户名 */
private String username;
/** 密码 */
private String password;
2、连接服务器
public boolean login() throws JSchException {
LOGGER.info("sftp login... ...");
JSch jsch = new JSch();
session = jsch.getSession(username, host, port);
if(password != null){
session.setPassword(password);
}
session.setConfig("StrictHostKeyChecking", "no");
session.setTimeout(timeout);
LOGGER.info("sftp login start... ...");
session.connect();
LOGGER.info("sftp login session connected");
channel = (ChannelSftp)session.openChannel("sftp");
LOGGER.info("sftp opening channel");
channel.connect();
LOGGER.info("sftp connected successfully");
return true;
}
3、下载
config 配置类
filepath 截取的远程路径
filename 截取的文件夹名称
截取filepath:
String filepath = path.substring(0, path.lastIndexOf("/"));
LOGGER.info("截取到的文件路径"+filepath);
截取filename:
String[] aa = path.split("/");
String filename = aa[aa.length - 1];
LOGGER.info("截取到的文件名"+filename);
public void downloadFile(Config config,String filepath,String filename) throws Exception {
LOGGER.info("下载开始");
String[] dirs = ls(config.getPath());
int length = dirs.length;
LOGGER.info("遍历的长度"+length);
for (int i = 0; i < dirs.length; i++) {
LOGGER.info(dirs[i]);
downloadFile(new File(dirs[i]),config.getPath());
}
}
(下载文件,递归循环,由于下载的是.xls文件,所以以文件后缀与是否为文件夹进行了判断条件)
private void downloadFile(File file,String path) throws Exception {
LOGGER.info("进来下载方法了");
boolean flag = true;
//OutputStream ops = null;
InputStream ips = null;
// 获取当日日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String format = sdf.format(new Date());
System.out.println("当日时间"+format);
//format = "20200409";
if(file.getName().endsWith(".xls")){
try {
LOGGER.info("开始下载");
System.out.println("文件名"+file.getName());
System.out.println("路径"+path);
Boolean b = null;
ips = channel.get(path + file.getName());
b = ips==null;
System.out.println("路径"+b);
upload(ips,file.getName(),format);
} catch (Exception e) {
e.printStackTrace();
LOGGER.info("下载文件失败");
}
}
else {
LOGGER.info("文件夹名称"+file);
String newPath = new String(path+file);
LOGGER.info("子文件夹远程路径"+newPath);
try {
// newLocalPath = newLocalPath + "/";
newPath = newPath + "/";
LOGGER.info("更换目标文件夹"+newPath);
String pwd = channel.pwd();
System.out.println("pwd"+pwd);
// 遍历文件夹
Vector<LsEntry> ls = channel.ls(newPath);
LOGGER.info("目录列表长度"+ls.size());
ArrayList<String> list = new ArrayList<>();
for (LsEntry entry : ls) {
System.out.println("hhhhhhhhhhhhh"+entry.getFilename());
if(filtertrue(entry,Filter.ALL)){
list.add(entry.getFilename());
}
}
String[] strings = list.toArray(new String[0]);
for (int i = 0; i < strings.length; i++) {
System.out.println("遍历的文件"+strings[i]);
if(strings[i] == format) {
File f = new File(strings[i]);
// 递归
downloadFile(f, newPath);
}else {
return;
}
}
}catch (SftpException e) {
e.printStackTrace();
LOGGER.info("遍历文件夹失败");
}
}
}
(上传B服务器,若为文件,转化为input流,为上传B服务器做准备)
public void upload(InputStream ips,String filename,String format) throws Exception {
ChannelSftp channel = null;
LOGGER.info("进入上传内部服务器");
Sftp sftp = new Sftp("ip", 22, 5000, "用户名", "密码");
channel = sftp.logingr();
LOGGER.info("连接内部服务器成功");
System.out.println("hhhh"+filename);
// 进入文件夹
channel.cd("/rooaa");
String pwd = channel.pwd();
System.out.println("pwd"+pwd);
// 创建日期目录
channel.mkdir(format);
File file = new File("/root/aa/"+format+"/"+filename);
//channel.cd(dir);
OutputStream out = null;
try {
out = channel.put(String.valueOf(file), ChannelSftp.OVERWRITE);
byte[] datas = new byte[1024*100];
int read = 0;
while ((read = ips.read(datas)) != -1) {
out.write(datas, 0, read);
}
boolean b = out == null;
System.out.println("是否有流"+b);
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (out != null) {
ips.close();
out.close();
}
}catch (IOException e) {
System.out.println("输出文件流异常");
LOGGER.info("输出文件流异常");
}
}
sftp.logout();
}
4.中间的引用方法
ls() 得到此路径下的文件及文件夹
pathname为参数传入的path:例如:“/aa/bb/”
public String[] ls(String pathName) throws SftpException{
String currentDir = currentDir();
if(!changeDir(pathName)){
return new String[0];
};
String[] result = list(Filter.ALL);
if(!changeDir(currentDir)){
return new String[0];
}
return result;
}
列出当前目录下的文件及文件夹
private String[] list(Filter filter){
Vector<LsEntry> list = null;
try {
//ls方法会返回两个特殊的目录,当前目录(.)和父目录(..)
list = channel.ls(channel.pwd());
} catch (SftpException e) {
LOGGER.error("can not list directory",e);
return new String[0];
}
List<String> resultList = new ArrayList<String>();
for(LsEntry entry : list){
if(filter(entry, filter)){
resultList.add(entry.getFilename());
}
}
return resultList.toArray(new String[0]);
}
过滤文件夹名称:
private boolean filtertrue(LsEntry entry,Filter f){
if(f.equals(Filter.ALL)){
return !entry.getFilename().equals(".") && !entry.getFilename().equals("..");
} else if(f.equals(Filter.FILE)){
return !entry.getFilename().equals(".") && !entry.getFilename().equals("..") && !entry.getAttrs().isDir();
} else if(f.equals(Filter.DIR)){
return !entry.getFilename().equals(".") && !entry.getFilename().equals("..") && entry.getAttrs().isDir();
}
return true;
}
Filter:枚举类·
private enum Filter {/** 文件及文件夹 */ ALL ,/** 文件 */ FILE ,/** 文件夹 */ DIR };
<遇到的问题:>
1、2: No such file 没有文件
2、 premi…(忘记了,是没有权限)
3、遍历文件夹的容器Vocter与List转换
4、A服务器下载完文件转化成流,进行B服务器上传过程时,出现ChannelSftp通道不一致,因此在做上传时,要重新建立通道对象
5、还有很多问题,有点健忘了,,,
<定时功能>
1、在启动类添加@EnableScheduling注解,
2、定时所在类添加@Component,交给spring容器管理
3、@Scheduled注解下的方法不能有参数
若有参数的报错:
Only no-arg methods may be annotated with @Scheduled
4、
@Scheduled(initialDelay = 10005,fixedRate = 1000606024)第一次执行延迟5秒,之后每天执行一次
@Scheduled(fixedDelay = 1000)上次执行完后一秒再执行一次
cron表达式,网上有好多,可以copy