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】