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;
    }
上一篇:Haproxy的负载均衡、动静分离、状态监控、近期网络架构


下一篇:nodejs 读取目前下所有文件