一 sftp搭建
略
这里简单说一下为什么使用sftp。ftp和sftp各有优点,差别并不是太大。sftp安全性好,性能比ftp低。ftp对于java来说并不复杂,效率也高。之所以使用sftp主要是可以使用spring-boot+apache-camel。camel框架将文件传输分为filter,prcessor,和路由,定时器等组件,模块化开发,将可随意将这些组件进行组合,耦合性低,开发较为灵活。可以将更多的精力放到业务层面。
二使用apache-camel来定时从sftp服务器下载文件
2.1 pom依赖
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>2.18.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ftp</artifactId>
<version>2.19.4</version>
</dependency>
2.2 applicatin.properties配置
ftp.server.uri=sftp://${ftp.url}\ ?username=${ftp.username}\ &password=${ftp.password}\ &useUserKnownHostsFile=false\ &localWorkDirectory=${ftp.local.work.directory}\ &delay=5m\ &filter=#ftpDownloadFileFilter\ &stepwise=false\ &recursive=true ftp.url=192.168.20.162:22/ ftp.username=test ftp.password=123456 #文件服务器目录 ftp.local.work.directory=/ # 文件拉取到本地存储的文件 ftp.local.data.dir=E://test/
其中
readLock=rename\ 是否重命名,防止读取文件服务器正在写入的文件
recursive=true 是否递归读取
#有些地方说这里需要显式指定后台运行
camel.springboot.main-run-controller=true
2.3 过滤器
自定义规则判断哪些文件需要下载,哪些文件不需要下载
package com.test.comm; import org.apache.camel.component.file.GenericFile; import org.apache.camel.component.file.GenericFileFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import com.test.util.RedisTemplateUtil; @Component public class FtpDownloadFileFilter implements GenericFileFilter<Object> { private static Logger logger = LoggerFactory.getLogger(FtpDownloadFileFilter.class); @Value("${ftp.local.data.dir}") private String localDir; @Autowired private RedisTemplateUtil redisTemplateUtil; /** * 过滤下载文件 * * @author sunk */ @Override public boolean accept(GenericFile<Object> file) { try { return isDownloaded(file); } catch (Exception e) { logger.error("ftp download file filter error !", e); return false; } } /** * 根据时间戳来判断是否下载过 * * @param fileName * * @return */ public boolean isDownloaded(GenericFile<Object> file) { String fileName = file.getFileName(); if (file.isDirectory()) { return true; } boolean bool = false; if (fileName.contains("_")) { long time = Long.parseLong(fileName.split("_")[3]); // 从redis中获取上次的时间,当前文件时间大于当前时间则获取,否则不获取 Object preTime = redisTemplateUtil.get(0, Constants.reids.YP_PICTRUE_TIME); if (preTime == null) { bool = true; } else { if (Long.parseLong(preTime.toString()) < time) { bool = true; } } } return bool; } }