注意!!! 本文是在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进行文件备份的更多相关文章

  1. 工具WinSCP:windows和Linux中进行文件传输

    工具WinSCP:windows和Linux中进行文件传输 2016-09-21 [转自]使用WinSCP软件在windows和Linux中进行文件传输 当我们的开发机是Windows,服务器是Lin ...

  2. Linux中检索文件

    1 , Use locate command It is a fast way to find the files location, but if a file just created ,it w ...

  3. Linux中查看文件编码

    在Linux中查看文件编码可以通过以下几种方式:1.在Vim中可以直接查看文件编码:set fileencoding即可显示文件编码格式.如果你只是想查看其它编码格式的文件或者想解决用Vim查看文件乱 ...

  4. 在Linux中查看文件的编码及对文件进行编码转换

    如果你需要在Linux中操作windows下的文件,那么你可能会经常遇到文件编码转换的问题.Windows中默认的文件格式是GBK(gb2312),而Linux一般都是UTF-8.下面介绍一下,在Li ...

  5. Linux中的文件描述符与打开文件之间的关系

    Linux中的文件描述符与打开文件之间的关系 导读 内核(kernel)利用文件描述符(file descriptor)来访问文件.文件描述符是非负整数.打开现存文件或新建文件时,内核会返回一个文件描 ...

  6. 5 个在 Linux 中管理文件类型和系统时间的有用命令

    对于想学习 Linux 的初学者来说要适应使用命令行或者终端可能非常困难.由于终端比图形用户界面程序更能帮助用户控制 Linux 系统,我们必须习惯在终端中运行命令.因此为了有效记忆 Linux 不同 ...

  7. Linux中一个文件10行内容,如何输出5-8内容到屏幕

    题目是这样的,Linux中一个文件10行内容,如何输出5-8内容到屏幕首先我们模拟一下这样的环境: [root@localhost question]# pwd /root/question [roo ...

  8. [转帖]NotePad++编辑Linux中的文件

    NotePad++编辑Linux中的文件 https://blog.csdn.net/chengqiuming/article/details/78882692 原作者 未经允许不允许转帖 加密自己参 ...

  9. linux中的文件编码及编码修改

    查看文件编码 在Linux中查看文件编码可以通过以下几种方式: 1.在Vim中可以直接查看文件编码 :set fileencoding 即可显示文件编码格式. 如果你只是想查看其它编码格式的文件或者想 ...

随机推荐

  1. 使用let实现循环小例子

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  2. VS在调试桌面程序时,cout到控制台方法

    参考博客:https://blog.csdn.net/xinxinsky/article/details/80733400 C++桌面程序设置 Properties -> Build Event ...

  3. 分享几个下载豆瓣资源的chrome插件

    最近chrome终于以4.69%的市场占有率击败firefox成为中国第二大浏览器.(第一当然是争霸宇宙的IE了) 虽然chrome官方应用程序商店有不少豆瓣的辅助插件,但大多没什么用.属于蛋疼插件. ...

  4. 【WPF】 OxyPlot图表控件学习

    最近在学习OxyPlot图表控件,一些基本的学习心得,在这里记录一下,方便以后进行查找.   一.引用 OxyPlot控件可以直接在VS的 " Nuget " 里面下载   选择: ...

  5. Metasploit用法详解

    Metasploit简介 1. Auxiliaries(辅助模块) 该模块不会直接在测试者和目标主机之间建立访问,它们只负责执行扫描.嗅探.指纹识别等相关功能以辅助渗透测试. 2. Exploit(漏 ...

  6. K8S日常运维中关于“ImagePullBackOff”报错的处理思路分析

    故障案例: 发现故障:kubectl get pod -n kube-system -owide|grep -v "Running"NAME READY STATUS RESTAR ...

  7. HTML一小时入门,半天掌握

    还没有写完,后续持续更新 首先来熟悉一下html的基本结构 <!DOCTYPE HTML> <html> <head> <meta charset=" ...

  8. 性能测试必备命令(3)- lscpu

    性能测试必备的 Linux 命令系列,可以看下面链接的文章哦 https://www.cnblogs.com/poloyy/category/1819490.html 介绍 显示有关CPU架构的信息 ...

  9. MySQL日志管理、备份、恢复

    目录: 一.MySQL 日志管理 二.数据库备份的重要性与分类 三.常见的备份方法 四.MySQL完全备份 五.数据库完全备份分类 六.MySQL增量备份 七.MySQL数据库增量恢复 八.MySQL ...

  10. sqlmap --eval 用法

    今天查资料发现 sqlmap 有一个 --eval 的参数 --eval=EVALCODE Evaluate provided Python code before the request (e.g. ...