一 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. 黄聪:PHP获取某一天前后任意时间

    date("Y-m-d",strtotime('-30 days',strtotime('2016-9-30')));

  2. MySql 的SQL执行计划查看,判断是否走索引

    在select窗口中,执行以下语句: set profiling =1; -- 打开profile分析工具show variables like '%profil%'; -- 查看是否生效show p ...

  3. Linux期中架构

    1    在构建完模板后  开启虚拟机后 需要再重启一次  以解决网卡不能看见的问题 ########################################add begin 2018-05 ...

  4. 使用nginx实现一个主机部署多域名指向不同docker项目

     1,安装 docker yum install docker 使用Docker 中国加速器 vim /etc/docker/daemon.json 添加下面代码 { "registry-m ...

  5. 在做MVC和WebApi写返回数据时,可以这样定义

    public class Messages { /// <summary> /// 返回包含是否成功以及消息字符结果 /// </summary> /// <param ...

  6. SUID、SGID详解

    文章转载至:http://tech.ccidnet.com/art/2583/20071030/1258885_1.html 如果你对SUID.SGID仍有迷惑可以好好参考一下! Copyright ...

  7. Spring获取URL相关信息

    获取请求的URL:request.getRequestURL().toString(); 获取上下文名称(项目名称):request.getContextPath()

  8. Java使用Jedis操作Redis大全

    Java操作Redis需要导入两个jar: commons-pool2-2.4.2.jar jedis-2.1.0.jar package com.chinasofti.test; import ja ...

  9. pandas数据结构之DataFrame操作

    这一次我的学习笔记就不直接用官方文档的形式来写了了,而是写成类似于“知识图谱”的形式,以供日后参考. 下面是所谓“知识图谱”,有什么用呢? 1.知道有什么操作(英文可以不看) 2.展示本篇笔记的结构 ...

  10. springboot 问题总结

    一:返回格式化日期 如果我们是用fastjson处理成jsonString,可以通过下面两种方式处理 1,在接受实体上@JSONField(format="yyyy-MM-dd HH:mm: ...