Linux中的文件使用FTP进行文件备份
注意!!! 本文是在linux中进行ftp备份(备份到另一个linux服务器)
上传思路:
1.每次上传文件时, 后台接收文件, 使用transferTo上传到Linux服务器
2.把文件路径 + File.separator + 文件名, 放入redis, 如果redis中已存在, 则用逗号(,)进行拼接, 代码在例1
3.每天凌晨1点, 从redis中取出文件路径进行ftp备份, 代码在例2
注意事项:
1.ftp上传时, 如果有相同文件名, 则必须判断(ftp不会自动覆盖文件), 否则会返回false
2.使用java代码进行切换目录时(ftpClient.changeWorkingDirectory("/")), 子目录名一定不能和父目录名重名, 否则进入父目录时, 会自动进入到子目录.
例:
现在有目录/home/test/, test下有2个文件夹:test,test1
我现在使用changeWorkingDirectory进入/home/test/test1, 程序会自动进入到/home/test/test, 然后进入test1, 这时就会报错
例:
例1:
String uppath = baseDir + File.separator + file.getOriginalFilename();
Object filePath = redisCache.getCacheObject("filePath");
if (filePath != null ) {
redisCache.setCacheObject("filePath", filePath + "," + uppath);
}else {
redisCache.setCacheObject("filePath", uppath);
}
例2:
@Scheduled(cron = "0 0 1 * * ?")
public void RedisErrInfoBackups() throws Exception {
log.info("redis FTP进行备份, 定时任务开始执行-----------------------------------------------");
String filePath = redisCache.getCacheObject("filePath") + "";
log.info(filePath);
if (StringUtils.isNotEmpty(filePath)) {
String[] fpath = filePath.split(",");
String sbr;
try {
sbr = FTPTools.upload("192.168.5.44", 14000, "PipBeiyuan", "123456o-0", fpath);
//上传失败时,添加到sbr, 重新放入redis,第二天继续进行备份
if (StringUtils.isNotEmpty(sbr)) {
if (sbr.endsWith(",")) {
sbr = sbr.substring(0, sbr.length() - 1);
}
redisCache.setCacheObject("filePath", sbr);
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
上传文件代码:
public static String upload(String hostname, int port, String username, String password, String[] fpath) {
FTPClient ftpClient = new FTPClient();
StringBuilder sbr = new StringBuilder();
//1 测试连接
if (connect(ftpClient, hostname, port, username, password)) {
try {
File file;
for (int i = 0, len = fpath.length; i < len; i++) {
file = new File(fpath[i]);
//判断文件是否存在(检查的是linux中的路径)
if(file.exists()) {
int index = fpath[i].lastIndexOf(File.separator);
//2 检查工作目录是否存在
if (changeWorkingDirectory(ftpClient,fpath[i].substring(0,index))) {
// 3 检查是否上传成功
log.info(fpath[i] + "---------开始上传");
if (storeFile(ftpClient, fpath[i].substring(index+1), new FileInputStream(fpath[i]))) {
log.info(fpath[i] + "----------备份上传成功");
} else {
sbr.append(fpath[i] + ",");
log.info(fpath[i] + "----------上传失败");
}
log.info(fpath[i] + "----------备份上传结束");
}
}
}
disconnect(ftpClient);
return sbr.toString();
} catch (IOException e) {
log.error("工作目录不存在");
e.printStackTrace();
disconnect(ftpClient);
}
}
return sbr.toString();
}
连接代码:
public static boolean connect(FTPClient ftpClient, String hostname, int port, String username, String password) {
boolean flag = false;
try {
//ftp初始化的一些参数
ftpClient.connect(hostname, port);
ftpClient.enterLocalPassiveMode();
ftpClient.setControlEncoding("UTF-8");
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.setConnectTimeout(60*1000);
if (ftpClient.login(username, password)) {
log.info("连接ftp成功");
flag = true;
} else {
log.error("连接ftp失败,可能用户名或密码错误");
try {
disconnect(ftpClient);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
log.error("连接失败,可能ip或端口错误");
e.printStackTrace();
}
return flag;
}
切换目录代码:
private static boolean changeWorkingDirectory(FTPClient ftpClient,String substring) throws IOException {
boolean isMakeSucess=false;
//先切换到根目录
ftpClient.changeWorkingDirectory("/");
//再按文件路径切换或者创建目录
for (String st : substring.split(/*File.separator*/"/")) {
if(StringUtils.isNotEmpty(st)){
if(!ftpClient.changeWorkingDirectory(st)){
isMakeSucess = ftpClient.makeDirectory(new String(st.getBytes("UTF-8"),"iso-8859-1"));
ftpClient.changeWorkingDirectory(st);
}else {
//切换路径
isMakeSucess = true;
ftpClient.changeWorkingDirectory(st);
}
}
}
return isMakeSucess;
}
上传代码:
public static boolean storeFile(FTPClient ftpClient, String fileName, InputStream fileInputStream) throws IOException {
boolean flag = false;
try {
//判断文件是否存在(如果存在继续上传会报错[不会自动覆盖])
log.info("当前路径为--> :" + ftpClient.printWorkingDirectory());
InputStream stream = ftpClient.retrieveFileStream(new String(fileName.getBytes("UTF-8"), FTP.DEFAULT_CONTROL_ENCODING));
//不存在则进行上传文件
if(stream == null || ftpClient.getReplyCode() == FTPReply.FILE_UNAVAILABLE){
if (ftpClient.storeFile(new String(fileName.getBytes("UTF-8"),"iso-8859-1"), fileInputStream)) {
log.info("不存在直接上传---:");
flag = true;
}
}else {
flag = true;
}
} catch (IOException e) {
log.error("上传失败");
e.printStackTrace();
}
return flag;
}
Linux中的文件使用FTP进行文件备份的更多相关文章
- 工具WinSCP:windows和Linux中进行文件传输
工具WinSCP:windows和Linux中进行文件传输 2016-09-21 [转自]使用WinSCP软件在windows和Linux中进行文件传输 当我们的开发机是Windows,服务器是Lin ...
- Linux中检索文件
1 , Use locate command It is a fast way to find the files location, but if a file just created ,it w ...
- Linux中查看文件编码
在Linux中查看文件编码可以通过以下几种方式:1.在Vim中可以直接查看文件编码:set fileencoding即可显示文件编码格式.如果你只是想查看其它编码格式的文件或者想解决用Vim查看文件乱 ...
- 在Linux中查看文件的编码及对文件进行编码转换
如果你需要在Linux中操作windows下的文件,那么你可能会经常遇到文件编码转换的问题.Windows中默认的文件格式是GBK(gb2312),而Linux一般都是UTF-8.下面介绍一下,在Li ...
- Linux中的文件描述符与打开文件之间的关系
Linux中的文件描述符与打开文件之间的关系 导读 内核(kernel)利用文件描述符(file descriptor)来访问文件.文件描述符是非负整数.打开现存文件或新建文件时,内核会返回一个文件描 ...
- 5 个在 Linux 中管理文件类型和系统时间的有用命令
对于想学习 Linux 的初学者来说要适应使用命令行或者终端可能非常困难.由于终端比图形用户界面程序更能帮助用户控制 Linux 系统,我们必须习惯在终端中运行命令.因此为了有效记忆 Linux 不同 ...
- Linux中一个文件10行内容,如何输出5-8内容到屏幕
题目是这样的,Linux中一个文件10行内容,如何输出5-8内容到屏幕首先我们模拟一下这样的环境: [root@localhost question]# pwd /root/question [roo ...
- [转帖]NotePad++编辑Linux中的文件
NotePad++编辑Linux中的文件 https://blog.csdn.net/chengqiuming/article/details/78882692 原作者 未经允许不允许转帖 加密自己参 ...
- linux中的文件编码及编码修改
查看文件编码 在Linux中查看文件编码可以通过以下几种方式: 1.在Vim中可以直接查看文件编码 :set fileencoding 即可显示文件编码格式. 如果你只是想查看其它编码格式的文件或者想 ...
随机推荐
- linux centos7 df命令
2021-08-04 1. df 命令简介 linux 中 df 命令的功能是用来检查 linux 服务器的文件系统的磁盘空间占用情况.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信 ...
- Git使用教程一
Git是一个分布式版本控制系统,简单的说其就是一个软件,用于记录一个或若 干文件内容变化,以便将来查阅特定版本修订情况的软件. Github (https://www.github.com) 是-一个 ...
- [bug]spring项目通过反射测试私有方法时,注入对象异常
背景 遇到问题:在进行Spring单元测试编写时,发现被测方法是一个私有方法,无法直接通过注入对象调用 解决思路:首先想到通过反射获取该私有方法的访问权限,并传入注入对象,最终调用对象的私有方法. 出 ...
- 【Azure 应用服务】Python flask 应用部署在Aure App Service 遇见的 3 个问题
在App Service(Windows)中部署Flask应用时的注意事项: ● 添加Python扩展插件,Python 3.6.4 x64: ●● 配置 FastCGI 处理程序,添加Web.con ...
- javaScript知识储备
javaScript知识储备 组成 ECMAScript(核心) 提供语法.变量等,遵循ECMA-262标准 DOM(文档对象模型) 提供操作HTML标签的API,遵循W3C规范 BOM(浏览器对象模 ...
- Docker下制作一个容器镜像
操作过程描述: (1)先基于centos的镜像启动一个centos容器 (2)在这个容器中安装nginx (3)然后把这个已经安装了nginx的容器制作成一个docker的镜像 操作:docker c ...
- 使用Mosquitto实现MQTT客服端C语言
上一篇文章已经将mosquitto移植到了arm平台上,现在将使用mosquitto完成mqtt客服端的demo,了解过mqtt协议的小伙伴都知道,mqtt主要分为代理服务器.发布者.订阅者三部分 ...
- Linux - yum 安装软件时被 PackageKit 锁定
问题描述 yum 安装软件的时候报错 sudo yum install netease-cloud-music 已加载插件:fastestmirror, langpacks /var/run/yum. ...
- Spring5(五)——AOP
一.AOP 1.介绍 AOP(Aspect Oriented Programming),面向切面编程.它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共 ...
- 从零开始学习SQL SERVER(1)--- 了解SQL
SQL是什么 SQL (发音为 sequal [' sikwəl ' ]) SQL指 Structured Query Language 结构化查询语言,是用于访问和处理数据库的标准的计算机语言. ...