注意!!! 本文是在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. 在ES5中模拟类

    1.Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__. var _this = Object.create(fn.prototype);这句代码的 ...

  2. Ubuntu 16.04 Install NVidia Driver (download from nvidia official site)

    sudo apt-get update sudo apt-mark hold libreoffice sudo apt-get update && sudo apt-get upgra ...

  3. os.read

    #-*-coding:utf-8-*-__author__ = "logan.xu"import oscmd_res=os.popen("ls").read() ...

  4. java变量类型和常量类型

    变量类型 局部变量 实例变量 类变量 public class 变量类型 { //属性:变量 //必须先定义再使用,并初始化 //布尔型:默认值为false //3. 类变量(静态变量) static ...

  5. Python之telnetlib模块

    telnetlib是python标准库中的一员,我们可以使用该模块以telnet的方式与服务器交互.请观察下面示例了解它的用法: import telnetlib def run_telnet(hos ...

  6. Pytest系列(22)- allure的特性,@allure.link()、@allure.issue()、@allure.testcase()的详细使用

    如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 上一篇文章介绍了两种allu ...

  7. Coreos配置docker镜像加速器

    CoreOS配置docker镜像加速器 CoreOS下的Docker配置是通过flannel unit来实现的. 1) 通过命令 systemctl cat docker 可以看出配置文件的默认位置 ...

  8. 处理burp log 小脚本

    burp 日志保存 保存的日志格式为 将日志中的数据包 每个数据包保存到一个单独的txt里面 然后可以控制目录放进不同的目录中 #coding=utf-8 import re import os de ...

  9. 线程调用BeginInvoke

    线程异步调用 Thread objThread = new Thread(new ThreadStart(delegate             {                 Dispatch ...

  10. Docker安装Nginx(含:Windows启动、重启、停止)

    Docker安装Nginx #docker pull nginx:latest (第一次启动Docker-Nginx) #docker run --detach \ --publish 80:80 \ ...