FTP文件同步(java版)

package com.ql.ftp;java

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;apache

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 ;
 }.net

 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);
  }
  
  //寫日誌文件orm

  //時間戳
  currTimestamp = Long.valueOf(dateFormat(new Date(),"yyyyMMddHHmmss"));server

  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】

相關文章
相關標籤/搜索