一 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;
} }

2.4 路由
自定义路由规则,一般是告诉程序,从哪里读文件,并搬运到哪里去

package com.test.comm;

import java.net.InetAddress;

import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
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; @Component
public class FtpDownloadRoute extends RouteBuilder { private static Logger logger = LoggerFactory.getLogger(FtpDownloadRoute.class); @Value("${ftp.server.uri}")
private String ftpUri; @Value("${ftp.local.data.dir}")
private String localDir; @Autowired
LocationFileProcessor locationFileProcessor; @Override
public void configure() throws Exception {
logger.debug("开始连接 " + ftpUri);
from(ftpUri).to("file:" + localDir).process(locationFileProcessor).log(LoggingLevel.INFO, logger,
"download file ${file:name} complete.");
logger.debug("连接成功");
} }

2.5 其它自定义进程
除了文件搬运之外,允许自定义对文件的其它操作,比如入库等等
,自定义的类,可添加在路由中

package com.test.comm;

import java.io.RandomAccessFile;
import java.util.HashMap; import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.component.file.GenericFileMessage;
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.google.gson.Gson;
import com.test.config.ApplicationStartup;
import com.test.model.Device;
import com.test.model.Pictrue;
import com.test.util.DateUtil;
import com.test.util.ESRepository;
import com.test.util.FileUtil;
import com.test.util.RedisTemplateUtil; /**
* camel 业务类
*
* <p>
* Title:LocationFileProcessor
* </p>
* <p>
* Description:TODO
* </p>
* <p>
* Copyright:Copyright(c)2005
* </p>
* <p>
* Company:stest
* </p>
*
* @author
* @date 2018年11月15日 上午9:02:29
*/
@Component
public class LocationFileProcessor implements Processor { private static Logger logger = LoggerFactory.getLogger(LocationFileProcessor.class); @Autowired
private RedisTemplateUtil redisTemplateUtil; @Autowired
private FastDFSClient fastDFSClient; @Value("${ftp.local.data.dir}")
private String localDir; @Autowired
private ESRepository eSRepository; @Value("${elasticsearch.index}")
private String esIndex; @Value("${elasticsearch.type}")
private String esType; @Autowired
private ApplicationStartup applicationStartup; @Override
public void process(Exchange exchange) throws Exception {
@SuppressWarnings("unchecked")
GenericFileMessage<RandomAccessFile> inFileMessage = (GenericFileMessage<RandomAccessFile>) exchange.getIn();
String fileName = inFileMessage.getGenericFile().getFileName();// 文件名
logger.info(fileName);// 文件的绝对路径
String subfileName = fileName.substring(fileName.lastIndexOf("/") + 1);
long time = Long.parseLong(fileName.split("_")[3]);
// 上传到fastdfs
String path = upload(fileName);
// 将图片地址等信息保存到es
saveEs(subfileName, path);
// 获取当前redis里面保存的时间,如果为空直接存入,如果不为空且当前文件时间大于redis时间,那覆盖
saveRedis(time);
} /**
* 将最后获取图片的时间标记保存至redis
*
* @param time
*/
private void saveRedis(long time) {
Object redisKey = redisTemplateUtil.get(0, Constants.reids.YP_PICTRUE_TIME);
if (redisKey == null || (redisKey != null && Long.parseLong(redisKey.toString()) < time)) {
redisTemplateUtil.set(Constants.reids.YP_PICTRUE_TIME, time, 0);
}
} /**
* 保存es
*
* @param subfileName
* @param path
*/
private void saveEs(String subfileName, String path) {
String[] fileNames = subfileName.split("_");
String deviceId = fileNames[0];
String plate = fileNames[2].substring(1);
String captrue = fileNames[3];
String type = fileNames[4].split("\\.")[0];
String times = DateUtil.transForDate1(Integer.parseInt(captrue));
captrue = captrue + "000";
// 根据deviceId获取经纬度
HashMap<Integer, Device> devices = applicationStartup.getDevices();
Device device = devices.get(Integer.parseInt(deviceId));
double latitude = 0;
double longitude = 0;
if (device != null) {
latitude = device.getLat();
longitude = device.getLon();
}
String deviceName = device.getDeviceName();
String address = device.getDeviceAddress();
Pictrue pictrue = new Pictrue(deviceId, plate, captrue, type, path, times, latitude, longitude, deviceName,
address, "视频数据");
Gson gson = new Gson();
eSRepository.addTargetDataALL(gson.toJson(pictrue), esIndex, esType, null);
} /**
* 上传fastdfs
*
* @param fileName
* @return
* @throws Exception
*/
private String upload(String fileName) throws Exception {
String path = fastDFSClient.uploadFile(FileUtil.getBytes(localDir + fileName), fileName);
return path;
}
}

spring boot + apache camel 传输文件的更多相关文章

  1. 快速搭建Spring Boot + Apache Shiro 环境

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.Apache Shiro 介绍及概念 概念:Apache Shiro是一个强大且易用的Java安全框 ...

  2. 从零开始的Spring Boot(3、Spring Boot静态资源和文件上传)

    Spring Boot静态资源和文件上传 写在前面 从零开始的Spring Boot(2.在Spring Boot中整合Servlet.Filter.Listener的方式) https://www. ...

  3. Spring Boot (30) 上传文件

    文件上传 上传文件和下载文件是Java Web中常见的一种操作,文件上传主要是将文件通过IO流传输到服务器的某一个文件夹下. 导入依赖 在pom.xml中添加上spring-boot-starter- ...

  4. 使用Spring boot + jQuery上传文件(kotlin)

    文件上传也是常见的功能,趁着周末,用Spring boot来实现一遍. 前端部分 前端使用jQuery,这部分并不复杂,jQuery可以读取表单内的文件,这里可以通过formdata对象来组装键值对, ...

  5. Spring Boot应用上传文件时报错

    问题描述 Spring Boot应用(使用默认的嵌入式Tomcat)在上传文件时,偶尔会出现上传失败的情况,后台报错日志信息如下:"The temporary upload location ...

  6. 在Spring Boot快捷地读取文件内容的若干种方式

    引言: 在Spring Boot构建的项目中,在某些情况下,需要自行去读取项目中的某些文件内容,那该如何以一种轻快简单的方式读取文件内容呢?  基于ApplicationContext读取 在Spri ...

  7. 手把手教你用 Spring Boot搭建一个在线文件预览系统!支持ppt、doc等多种类型文件预览

    昨晚搭建环境都花了好一会时间,主要在浪费在了安装 openoffice 这个依赖环境上(Mac 需要手动安装). 然后,又一步一步功能演示,记录,调试项目,并且简单研究了一下核心代码之后才把这篇文章写 ...

  8. spring boot自定义log4j2日志文件

    背景:因为从 spring boot 1.4开始的版本就要用log4j2 了,支持的格式有json和xml两种格式,此次实践主要使用的是xml的格式定义日志说明. spring boot 1.5.8. ...

  9. Spring Boot会员管理系统——处理文件上传

    温馨提示 Spring Boot会员管理系统的中,需要涉及到Spring框架,SpringMVC框架,Hibernate框架,thymeleaf模板引擎.所以,可以学习下这些知识.当然,直接入门的话使 ...

随机推荐

  1. VS2017编译GDAL(64bit)+解决C#读取Shp数据中文路径的问题

    编译GDAL过程比较繁琐,查阅了网上相关资料,同时通过实践,完成GDAL的编译,同时解决了SHP数据中文路径及中文字段乱码的问题,本文以“gdal-2.3.2”版本为例阐述整个编译过程. 一.编译准备 ...

  2. (转)PHP线程安全与非线程安全的区别:如何选择用哪一个?

    PHP线程安全与非线程安全的区别:如何选择用哪一个? 很多时候,我们在做PHP环境配置的时候,很多人都是直接去乱下载PHP版本的,但是他不清楚:从2000年10月20日发布的第一个Windows版的P ...

  3. 为什么比特币和以太坊未必真得比EOS更去中心化?

    在区块链行业里,有两派人一直在争论:一个是以比特币和以太坊为首的社群,另一个是以EOS为首的社群.这两群人一直在争论谁才是真正的未来,双方都认为自己这边更有未来.其中EOS抗争的重点就是100万TPS ...

  4. [UE4]抓取准备

    一.引擎的VR实例工程是使用手柄进行抓取的.我们需要加上可以使用鼠标进行抓取操作. 二.将左右手保存到全局变量. 三.左右手分别调用抓取和扔方法

  5. Centos 7环境下配置MySQL 5.7读写分离

    1.实验目的: 实现在Centos 7系统环境下,MySQL5.7读写分离. 2.实验条件: MySQL主服务器:Centos 7桌面环境,IP:10.10.11.31 MySQL从服务器:Cento ...

  6. 常用内置函数_eval_exce

    内置函数 abs 绝对值函数 res = abs(-19) print(res) round 四舍五入(n.5时, 奇数进偶数不进) sum 计算序列的和(元素是数字类型) listvar = (1, ...

  7. idea启动tomcat 找不到 类,或者报Error configuring application listener of class org.springframework.web.context.ContextLoaderListener

    这主要是打成war包的时候没有讲导入的jar也添加进去,只需要添加进来就行啦 可以看到WEB-INF目录下没有lib目录 put into output root 就可以了 然后就可以啦

  8. 学习MeteoInfo二次开发教程(十一)

    1.新添加状态栏ToolStrip,可能名称为toolStripStatusLabel2 这时需要把TSSL_Coord改为toolStripStatusLabel2 2.SetMapView();语 ...

  9. 使用QQ传输大文件

    现在在公网上能传输大文件并且稳定支持断点续传的软件非常少了,可以使用qq来做这件事. qq传输单个文件有时候提示不能超过4g有时候提示不能超过60g,没搞明白具体怎么样. 可以使用qq的传输文件夹功能 ...

  10. String 相关

    1. 输出结果为 true,"hello" + 1 在编译期间就被优化成了 "hello1",因此在运行期间,变量 a 和变量 b 指向的是同一个对象 Stri ...