FTP文件同步(java版)

package com.ql.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import ch.ubique.inieditor.IniEditor;

public class Filesysc {

 public final static  String LOG_FILE_DIR = "f:/ftp/log";
 public final static String FILESYSC_FILE_PATH = "f:/ftp/filesync.ini";
 public static FileWriter fileWriter = null ;
 public static Long currTimestamp = 0L;   //时间戳
 
 
 //获取需要同步的文件,返回false:没有需要同步的文件,true:有文件需要同步
 public static boolean getSyncFile(List<File> lstFile,IniEditor iniInfo) throws IOException{
  
  String srcdir = iniInfo.get("FILESYNC", "SRCDIR");
  String timestamp = iniInfo.get("FILESYNC", "TIMESTAMP");
  
  //本地同步目录
  File locDir = new File(srcdir);
  
  //查询需要同步的文件,并存放在lstFile中(记录在filesync.ini文件的时间戳:timestamp)
  qryFile(locDir,lstFile,Long.valueOf(timestamp));

  int len = lstFile.size();
  
  //日志文件不存在,则创建该日志文件(日志文件:sync_yyyyMMdd.log)
  String logFile = getLogFile(LOG_FILE_DIR);
  fileWriter = new FileWriter(logFile, true);
  fileWriter.write("\n\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")+"----> 文件同步开始......");
  
  if(len == 0){
   fileWriter.write("\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")+"----> 没有需要同步的文件!");
   fileWriter.close();
   return false;
  }else{
   fileWriter.write("\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")+"----> 文件扫描完成,需要同步文件 "+len+" 个,同步开始");
  }
  
  //对存放在lstFile中的文件按修改时间排序
  File file = null;
  for(int i=0;i<len;i++){
   for(int j=0;j<len-1;j++){
    if(lstFile.get(j).lastModified()>lstFile.get(j+1).lastModified()){
     file = lstFile.get(j);
     lstFile.set(j, lstFile.get(j+1)) ;
     lstFile.set(j+1, file) ;
    }
   }
  }
  
  System.out.println("***************************************");
  for(File f:lstFile){
   System.out.println(f.getAbsolutePath());
  }
  System.out.println("***************************************");
  return true ;
 }

 public static void main(String[] args) throws IOException {
  
  //读取filesync.ini文件配置
  IniEditor iniInfo = getIniInfo(FILESYSC_FILE_PATH);
  
  List<File> lstFile = new ArrayList<File>();
  
  //获取排好的需要同步的文件lstFile
  boolean b = getSyncFile(lstFile,iniInfo);
  
  if(!b)
   return  ;
  
  boolean res = false ;
  
  //同步本地文件到FTP服务器
  res = syncFiles(lstFile,iniInfo);
  
  
  //同步成功时,才保存时间戳,否则不保存时间戳
  if(res){
   iniInfo.set("FILESYNC", "TIMESTAMP",String.valueOf(currTimestamp));
   iniInfo.save(new File(FILESYSC_FILE_PATH));
  }
  
 }
 
 public static boolean syncFiles(List<File> lstFile,IniEditor iniInfo) throws IOException{

  String srcdir = iniInfo.get("FILESYNC", "SRCDIR");
  String server = iniInfo.get("FILESYNC", "SERVER");
  String port = iniInfo.get("FILESYNC", "PORT");
  String user = iniInfo.get("FILESYNC", "USER");
  String password = iniInfo.get("FILESYNC", "PASSWORD");
  
  if(fileWriter == null){
   String logFile = getLogFile(LOG_FILE_DIR);
   fileWriter = new FileWriter(logFile, true);
  }
  
  //写日志文件

  //时间戳
  currTimestamp = Long.valueOf(dateFormat(new Date(),"yyyyMMddHHmmss"));

  fileWriter.write("\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")+"----> 开始同步文件,时间戳为:"+currTimestamp);

   //本地目录的字符数
   int n = srcdir.length();
  
   //同步List
   List<File> syncList = Collections.synchronizedList(lstFile);
  
  FTPClient ftpClient = new FTPClient();
  
  //登陆FTP
  boolean b_login = loginFtp(ftpClient,server,Integer.valueOf(port),user,password,fileWriter);
  
  if(!b_login){
   fileWriter.write("\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")+"---->  登陆FTP失败......");
   if(fileWriter != null)
    fileWriter.close();
   return false ;
  }
  
  // 设置被动模式
  ftpClient.enterLocalPassiveMode();
  
  // 设置以二进制方式传输,不能设置此选项
  ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

  //下面三行代码必须要,而且不能改变编码格式
  ftpClient.setControlEncoding("GBK");
  FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
  conf.setServerLanguageCode("zh");
  
  
  boolean b = false ;
  
  //循环上传需要同步的文件到FTP服务器上
  for(File f:syncList){
   synchronized(Filesysc.class){
   f.getParentFile().getPath();
   String path = f.getParentFile().getPath().substring(n-1);
   InputStream input=new FileInputStream(f);
   path = new String(path.getBytes("GBK"),"ISO8859-1");
   String filename = new String(f.getName().getBytes("GBK"),"ISO8859-1");
   
   b = uploadFile(ftpClient, path,filename,input,fileWriter);
   
   if(!b){
    try {
     Thread.sleep(1000);
     for(int i=1;i<=10;i++){
      input=new FileInputStream(f);
      System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~  ---> path="+new String(path.getBytes("ISO8859-1"),"GBK"));
      b = uploadFile(ftpClient, path,filename,input,fileWriter);
      
      System.err.println("~~~~~~~~~~~~~~~~~~~~   --->"+i+"  "+new String(filename.getBytes("ISO8859-1"),"GBK")+"--->"+(b)+"~~~~~~~~~~~~~~~~~~");
      if(b){
       fileWriter.write("\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")
                 +"----> 文件["+new String(filename.getBytes("ISO8859-1"),"GBK")+"]同步成功!");
       break;
      }else{
       fileWriter.write("\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")
                 +"----> 文件["+new String(filename.getBytes("ISO8859-1"),"GBK")
                       +"]同步失败,错误原因:上传该文件时出现异常!");
      }
     }
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    
    //最终还是有文件不能成功 上传,则退出程序
    if(!b)
     break;
   }else{
    input.close();
   }

   }
  }
  
  
  ftpClient.logout();
  ftpClient.disconnect();

  if(b)
   fileWriter.write("\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")+"---->文件同步完成,共同步文件"+lstFile.size()+" 个");
  else
   fileWriter.write("\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")+"---->文件同步失败......");
  
  if(fileWriter != null)
   fileWriter.close();

  return b ;
 }
 
 //加载filesysc.ini文件
 public static IniEditor getIniInfo(String fileName){
  File file = new File(fileName);
  IniEditor ini = new IniEditor();
  try {
   ini.load(file);
  } catch (IOException e) {
   System.out.println("获取filesysc.ini文件信息时,出现异常");
   e.printStackTrace();
  }
  return ini ;
 }
 
 //登陆FTP
 public static boolean loginFtp(FTPClient ftpClient,String server,int port,String user,String password,FileWriter fileWriter){
  boolean b = false ;
  try {
   ftpClient.connect(server, port);
   b = ftpClient.login(user, password);
  } catch (Exception e) {
   try {
    fileWriter.write("\n"+dateFormat(new Date(),"yyyy-MM-yy HH:mm:ss")+"---->"+e.getMessage());
   } catch (IOException e1) {
    e1.printStackTrace();
   }
  }
  return b;
 }
 
 //得到日志文件绝对路径,不存在则创建
 public static String getLogFile(String path) throws IOException{
  File dir = new File(path);
  if(!dir.exists()){
   dir.mkdirs();
  }
  String logFile = path+"/sync_"+dateFormat(new Date(),"yyyyMMdd")+".log";
  File file = new File(logFile);
  
  if(!file.exists()){
   file.createNewFile();
  }
  return logFile;
 }
 
 //格式化时间
 public static String dateFormat(Date date,String format){
  SimpleDateFormat sdf = new SimpleDateFormat(format);  
  return sdf.format(date);
 }

 //查询目录中大于时间戳的所有文件
 public static void qryFile(File file,List<File> lstFile,long timestamp){
  
  if(file.isFile()&& timestamp < Long.valueOf(dateFormat(new Date(file.lastModified()),"yyyyMMddHHmmss"))){
   System.err.println("递归文件------------->"+file.getPath());
   lstFile.add(file);
  }else{
   System.err.println("递归文件夹-------------->"+file.getPath());
   File[] files = file.listFiles();
   for(File f:files){
    if(f.isFile() && timestamp < Long.valueOf(dateFormat(new Date(f.lastModified()),"yyyyMMddHHmmss"))){
     lstFile.add(f);
     System.out.println("递归文件-------------->"+f.getPath());
    }else if(f.isDirectory()){
     qryFile(f,lstFile,timestamp);
    }
   }
  }
 }
 
 /**
  * Description: 向FTP服务器 单个上传文件
  * @param path FTP服务器保存目录
  * @param filename 上传到FTP服务器上的文件名
  * @param input 输入流
  * @return 成功返回true,否则返回false
  * @throws IOException
  */
 public static  boolean uploadFile(FTPClient ftpClient, String path, String filename, InputStream input, FileWriter writer ) { 
     boolean success = false; 
     String pth = path ;
     try {
      //切换到默认目录
      ftpClient.changeWorkingDirectory(""); 
      
      //切换FTP服务器存放文件的目录
      if(!"".equals(pth)){
       pth = pth.replace("\\", "/");
       String[] arr= pth.split("/");
       
       for(String p:arr){
        p = p.trim();
        if(!"".equals(p)){
         if(!ftpClient.changeWorkingDirectory(p)){
          ftpClient.makeDirectory(p);
         }
         //切换FTP目录
         ftpClient.changeWorkingDirectory(p);
        }
       }
      }
      
      ftpClient.enterLocalPassiveMode();

      //删除该目录上的同名文件
      ftpClient.deleteFile(filename);
       
      
      System.out.println("---------------------> uploadFile filename="+new String(filename.getBytes("ISO8859-1"),"GBK"));
      
      success = ftpClient.storeFile(filename, input);
        
         if(input != null)
          input.close();
        
     } catch (IOException e) { 
      
      try {
       if(input != null)
           input.close();
       
    System.err.println("上传"+new String(filename.getBytes("ISO8859-1"),"GBK")+"    失败......");
    if(input != null)
     input.close();
   } catch (UnsupportedEncodingException e3) {
    e3.printStackTrace();
   } catch (IOException e1) {
    e1.printStackTrace();
   }

     }
     return success; 
 }
 
}

 

filesync.ini文件格式:

[filesync]
srcdir = F:/qianlong/
server = 192.168.3.101
port = 21
user = anonymous
password =
timestamp = 20120914144202

注:可以同步中文目录及中文名称文件,当文件比较大时,容易同步失败。代码简单、易懂。参考了网上一些代码。

【使用 commons-net-2.2.jar、inieditor-r2.jar】

转载于:https://my.oschina.net/u/180766/blog/78568

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值