一 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. WIMLIB-CAPTURE捕获说明

    WIMLIB-CAPTURE捕获说明1.如果捕获目录Y:\windows,那么[ExclusionList]字段里面不能有\windows,否则什么都不能捕捉,但是可以有下面的子目录例如\window ...

  2. kafka 暂停消费

    1.代码实现 kafkaListener 需要指定id,例如这里是:full-part-id. @KafkaListener(topics = "part-full-topic", ...

  3. Python【每日一问】08

    问:请解释一下装饰器的本质.功能 答: 1.装饰器的本质:闭包函数 2.装饰器的功能:在不改变函数本体结构.调用方法的情况下,给函数添加额外的功能 3.装饰器的实现方式 装饰器的实现方式一般是: de ...

  4. Docker学习系列之一——安装篇

    一.目的 Docker是目前非常流行的虚拟技术,在云计算领域得到了广泛的应用.国内的阿里.京东等大厂都非常普遍地应用了Docker.本文记录了Docker的基本安装过程及最终运行结果,以期备忘,及和同 ...

  5. php变量函数

    这个东西相当于C语言中的函数指针,C#里的委托   function come() {                   //定义com函数 echo "来了<p>" ...

  6. hdfs知识点《转》

    HDFS知识点总结   学习完Hadoop权威指南有一段时间了,现在再回顾和总结一下HDFS的知识点. 1.HDFS的设计 HDFS是什么:HDFS即Hadoop分布式文件系统(Hadoop Dist ...

  7. centos7 安装远程桌面

    https://www.linuxidc.com/Linux/2017-09/147050.htm https://blog.csdn.net/dazhi_1314/article/details/7 ...

  8. 对map集合按照value从大到小进行排序

    概述: 基本特点: 该集合存储键值对,而且要保证键的惟一性 子类: |--HashTable 底层是哈希数据表结构,不可以使用Null作为键或者值:该集合线程是同步的 |--hashMap   底层是 ...

  9. JavaScript数组方法--filter、find、findIndex

    继续数组方法,今天应该到filter了. filter:filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素. 使用: var words = ['spray', 'lim ...

  10. golang 统计uint64 数字二进制存储中1的数量

    package main import (    "fmt") // pc[i] is the population count of i.var pc [256]byte fun ...