很多人都碰到ftp的上傳下載文件的實現(xiàn),很容易碰到一些問題,最難解決的是亂碼的問題,
在網上搜索了挺多,也沒人能講得清楚詳細的,這里把自己實現(xiàn)的程序貼出來,供大家參考。
以后碰到這些問題,可以自己多看看java的API,還是很有幫助的。
    另外在實現(xiàn)ftp上傳下載的時候,還要多考慮一下上傳下載失敗或者網絡連接斷開的問題,
這需要不同情況不同的處理了,這里不作描述了。
    
    1> 解決亂碼的關鍵
    FtpClient的默認編碼格式ISO-8859-1,很多地方都提到了sun.net.NetworkClient類中的encoding屬性,
能設置ftp的編碼格式,但這個屬性是不能直接訪問的,可以通過繼承FtpClient類的方式來訪問;

 

/**
 * 
 * <p>Title: FtpOperation.java</p>
 * <p>Description: 為了改變FtpClient的默認編碼格式ISO-8859-1為utf-8(或GBK)支持中文,實現(xiàn)了此類繼承FtpClient</p>
 * <p>Copyright: Copyright (c) 2009</p>
 * <p>Company: </p>
 * 
@author 
 * 
@version 1.0 
 *
 
*/

public class CustomFtpClient extends FtpClient {

 
private CustomFtpClient() {
  
super();
 }

 
/**
  * 初始化時必須指定服務器的編碼格式
  * 
@param encodingStr
  
*/

 
protected CustomFtpClient(String encodingStr) {
  
super();
  sun.net.NetworkClient.encoding 
= encodingStr;
 }


 
/**
  * 設置連接編碼 
  * 
@param encodingStr
  * void
  *
  
*/

 
protected void setEncoding(String encodingStr) {
  sun.net.NetworkClient.encoding 
= encodingStr;
 }

 
/**
  * 取得編碼格式
  * 
@return
  * String
  *
  
*/

 
protected String getEncoding() {
  
return sun.net.NetworkClient.encoding ;
 }

}


2. 這個類就是ftp上傳下載的處理類,主要是注意對連接的處理和一些細節(jié)問題,也比較簡單,就是要仔細點,這里不啰嗦了。
/**
 * 
 * <p>
 * Title: FtpUtils.java
 * </p>
 * <p>
 * Description: FTP相關的操作類,提供ftp登錄、ftp上傳文件、ftp下載文件等功能<br/>
 * 使用說明:<br/>
 * FtpUtil ftp = new FtpUtil("localhost", "test", "test", "GBK","test", 21); //初始化信息<br/>
 * ftp.connectServer();<br/>
 *    如果需要以ascii格式操作,要調用方法ftp.ftpClient.ascii();<br/>
 * **ftp的相關操作**<br/>
 * ftp.closeConnect();<br/>
 * </p>
 * <p>
 * Copyright: Copyright (c) 2009
 * </p>
 * <p>
 * Company: 
 * </p>
 * 
 * 
@author 
 * 
@version 1.0
 * 
 
*/

public class FtpUtil {

    
private String serverIp = ""// 服務器ip

    
private String userName = ""// 登錄服務器用戶名

    
private String password = ""// 登錄服務器密碼

    
private String path = ""// 服務器路徑

    
private int serverPort = -1// 服務器端口號
    
    
private String encoding = "GBK"//服務器端編碼格式

    
protected CustomFtpClient ftpClient = null;

    OutputStream os 
= null;

    FileInputStream is 
= null;

    
/**
     * 構造函數(shù),用配置文件asiainfo.properties中配置的ftp信息進行操作,
     * 需要設置服務器的編碼格式PLANDEMO_FTP_ENCODING="GBK"(ftp服務器編碼格式)。
     * 
@param encodingStr
     * 
@throws Exception
     
*/

    
public FtpUtil() throws Exception {
        
try {
            
this.serverIp = Configure.getInstance().getProperty(
                    
"PLANDEMO_FTP_SERVER"); // 默認服務器
            this.userName = Configure.getInstance().getProperty(
                    
"PLANDEMO_FTP_USERNAME"); // 默認用戶
            this.password = Configure.getInstance().getProperty(
                    
"PLANDEMO_FTP_PASSWORD"); // 默認密碼
            this.path = Configure.getInstance().getProperty("PLANDEMO_FTP_DIR"); // 默認路徑
            this.encoding = StringUtil.obj2Str(Configure.getInstance().getProperty("PLANDEMO_FTP_ENCODING"),"GBK"); // 默認路徑
        }
 catch (Exception ex) {
            ex.getMessage();
        }

    }


    
/**
     * 構造函數(shù) 用傳入的參數(shù)進行ftp操作,必須確定ftp服務器的編碼格式
     * 
@param ip
     *            服務器ip地址
     * 
@param name
     *            登錄服務器用戶名
     * 
@param pwd
     *            登錄服務器密碼
     * 
@param encodingStr    ftp服務器的編碼格式
     * 
@param defPath
     *            服務器設置的路徑,為空則為默認設置的路徑
     * 
@param port
     *            如果采用服務器默認值設置為-1,其他需要設置
     
*/

    
public FtpUtil(String ip, String name, String pwd, String encodingStr, String defPath, int port) {
        
this.serverIp = ip;
        
this.userName = name;
        
this.password = pwd;
        
this.encoding = StringUtil.obj2Str(encodingStr,"GBK");
        
this.path = defPath;
        
this.serverPort = port;
    }


    
/**
     * 
     * 連接服務器
     * 
     * 
@return String 如果連接成功返回"true",失敗則返回"連接錯誤或服務器上無此路徑!"
     * 
     
*/

    
public String connectServer() {
        
try {
            ftpClient 
= new CustomFtpClient(this.encoding);
            
if (this.serverPort > 0{
                ftpClient.openServer(
this.serverIp, this.serverPort);
            }
 else {
                ftpClient.openServer(
this.serverIp);
            }


            ftpClient.login(
this.userName, this.password);
            
if (this.path != null && this.path.trim().length() > 0{
                ftpClient.cd(
this.path);
            }

            ftpClient.binary();
            
return "true";
        }
 catch (Exception ex) {
            ex.printStackTrace();
            
return "連接錯誤或服務器上無此路徑!";
        }

    }


    
/**
     * 根據(jù)傳入的文件路徑進行連接。
     * 
     * 
@param hostPath
     *            傳入的服務器路徑
     * 
@return String 如果連接成功返回"true",沒有該路徑返回"連接錯誤或服務器上無此路徑!"
     * 
     
*/

    
public String connectServer(String hostPath) {
        
try {
            ftpClient 
= new CustomFtpClient(this.encoding);
            
if (this.serverPort > 0{
                ftpClient.openServer(
this.serverIp, this.serverPort);
            }
 else {
                ftpClient.openServer(
this.serverIp);
            }

            ftpClient.login(
this.userName, this.password);
            
if (hostPath != null && hostPath.trim().length() > 0{
                ftpClient.cd(hostPath);
            }

            ftpClient.binary();
            
return "true";
        }
 catch (Exception ex) {
            ex.printStackTrace();
            
return "連接錯誤或服務器上無此路徑!";
        }

    }


    
/**
     * 
     * 關閉連接 void
     * 
     
*/

    
public void closeConnect() {
        
try {
            
if (is != null{
                is.close();
            }

            
if (os != null{
                os.close();
            }

            
if (ftpClient != null && ftpClient.serverIsOpen()) {
                ftpClient.closeServer();
            }

        }
 catch (Exception ex) {
            ex.printStackTrace();
        }

    }


    
/**
     * 
     * 從ftp下載文件到本地
     * 
     * 
@param filename            服務器上的文件名(與服務器路徑的相對路徑和文件名)
     * 
@param newfilename    本地生成的文件名(不帶路徑會下載到默認的項目的根目錄)
     * 
@return
     * long        下載文件的大小,以字節(jié)為單位,下載失敗返回-1
     *
     
*/

    
public long downloadFile(String filename, String newfilename) {
        TelnetInputStream is 
= null;
        FileOutputStream os 
= null;
        
long result =0;
        
try {
            is 
= ftpClient.get(filename);
            java.io.File outfile 
= new java.io.File(newfilename);
            os 
= new FileOutputStream(outfile);
            
byte[] bytes = new byte[1024];
            
int c;
            
while ((c = is.read(bytes)) != -1{
                os.write(bytes, 
0, c);
                result 
+= c;
            }

            
return result;
        }
 catch (IOException e) {
            e.printStackTrace();
            
return -1;
        }
 finally {
            
try {
                
if (is != null{
                    is.close();
                }

                
if (os != null{
                    os.close();
                }

            }
 catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    
/**
     * 
     * 獲取ftp服務器上的文件大小
     * 
@param filename
     * 
@return
     * long        指定文件的大小,以字節(jié)為單位,讀取文件異常返回-1
     *
     
*/

    
public long getFileSize(String filename) {
        TelnetInputStream is 
= null;
        
long result =0;
        
try {
            is 
= ftpClient.get(filename);
            
byte[] bytes = new byte[1024];
            
int c;
            
while ((c = is.read(bytes)) != -1{
                result 
+= c;
            }

            
return result;
        }
 catch (IOException e) {
            e.printStackTrace();
            
return -1;
        }
 finally {
            
try {
                
if (is != null{
                    is.close();
                }

                
if (os != null{
                    os.close();
                }

            }
 catch (IOException e) {
                e.printStackTrace();
            }

        }

    }


    
/**
     * 
     * ftp上傳 如果服務器段已存在名為filename的文件夾,該文件夾中與要上傳的文件夾中同名的文件將被替換
     * 
     * 
@param filename
     *            要上傳的文件(或文件夾)名
     * 
@return
     * boolean
     *
     
*/

    
public boolean upload(String filename) {
        String newname 
= "";
        
if (filename.indexOf("/"> -1{
            newname 
= filename.substring(filename.lastIndexOf("/"+ 1);
        }
 else if(filename.indexOf("\\"> -1{
            newname 
= filename.substring(filename.lastIndexOf("\\"+ 1);
        }
else {
            newname 
= filename;
        }

        
return upload(filename, newname);
    }


    
/**
     * 
     * ftp上傳 如果服務器段已存在名為newName的文件夾,該文件夾中與要上傳的文件夾中同名的文件將被替換
     * 
     * 
@param fileName
     *            要上傳的文件(或文件夾)名
     * 
@param newName
     *            服務器段要生成的文件(或文件夾)名
     * 
@return
     * boolean
     *
     
*/

    
public boolean upload(String fileName, String newName) {
        
try {
            File file_in 
= new File(fileName);// 打開本地待上傳的文件
            if (!file_in.exists()) {
                
throw new Exception("此文件或文件夾[" + file_in.getName() + "]有誤或不存在!");
            }

            
if (file_in.isDirectory()) {
                upload(file_in.getPath(), newName, ftpClient.pwd());
            }
 else {
                uploadFile(file_in.getPath(), newName);
            }


            
if (is != null{
                is.close();
            }

            
if (os != null{
                os.close();
            }

            
return true;
        }
 catch (Exception e) {
            e.printStackTrace();
            System.err.println(
"Exception e in Ftp upload(): " + e.toString());
            
return false;
        }
 finally {
            
try {
                
if (is != null{
                    is.close();
                }

                
if (os != null{
                    os.close();
                }

            }
 catch (IOException e) {
                e.printStackTrace();
            }

        }

    }


    
/**
     * 上傳文件或者文件夾
     * 
     * 
@param fileName
     * 
@param newName
     * 
@param path
     * 
@throws Exception
     
*/

    
private void upload(String fileName, String newName, String path)
            
throws Exception {
        File file_in 
= new File(fileName);// 打開本地待長傳的文件
        if (!file_in.exists()) {
            
throw new Exception("此文件或文件夾[" + file_in.getName() + "]有誤或不存在!");
        }

        
if (file_in.isDirectory()) {
            
if (!isDirExist(newName)) {
                createDir(newName);
            }

            ftpClient.cd(newName);
            File sourceFile[] 
= file_in.listFiles();
            
for (int i = 0; i < sourceFile.length; i++{
                
if (!sourceFile[i].exists()) {
                    
continue;
                }

                
if (sourceFile[i].isDirectory()) {
                    
this.upload(sourceFile[i].getPath(), sourceFile[i]
                            .getName(), path 
+ File.separator + newName);
                }
 else {
                    
this.uploadFile(sourceFile[i].getPath(), sourceFile[i]
                            .getName());
                }

            }

        }
 else {
            uploadFile(file_in.getPath(), newName);
        }

        ftpClient.cd(path);
    }


    
/**
     * 
     * upload 上傳文件
     * 
@param filename
     *            要上傳的文件名
     * 
@param newname
     *            上傳后的新文件名
     * 
@return
     * 
@throws Exception
     * long        已經上傳文件的大小,異常返回-1
     *
     
*/

    
public long uploadFile(String filename, String newname) throws Exception {
        TelnetOutputStream os 
= null;
        FileInputStream is 
= null;
        
long result =0;
        
try {
            java.io.File file_in 
= new java.io.File(filename);
            
if (!file_in.exists()) {
                
return -1;
            }

            os 
= ftpClient.put(newname);
            is 
= new FileInputStream(file_in);
            
byte[] bytes = new byte[1024];
            
int c;
            
while ((c = is.read(bytes)) != -1{
                os.write(bytes, 
0, c);
                result 
+= c;
            }

            
return result;
        }
 finally {
            
if (is != null{
                is.close();
            }

            
if (os != null{
                os.close();
            }

        }

    }


    
/**
     * 檢查文件夾在當前目錄下是否存在
     * 
     * 
@param dir
     * 
@return
     
*/

    
public boolean isDirExist(String dir) {
        String pwd 
= "";
        
try {
            pwd 
= ftpClient.pwd();
            ftpClient.cd(dir);
            ftpClient.cd(pwd);
        }
 catch (Exception e) {
            
return false;
        }

        
return true;
    }


    
/**
     * 在當前目錄下創(chuàng)建文件夾
     * 
     * 
@param dir
     * 
@return
     * 
@throws Exception
     
*/

    
public boolean createDir(String dir) {
        
try {
            ftpClient.ascii();
            StringTokenizer s 
= new StringTokenizer(dir, File.separator); // sign
            s.countTokens();
            String pathName 
= ftpClient.pwd();
            
while (s.hasMoreElements()) {
                pathName 
= pathName + File.separator + (String) s.nextElement();
                
try {
                    ftpClient.sendServer(
"MKD " + pathName + "\r\n");
                }
 catch (Exception e) {
                    e.printStackTrace();
                    
return false;
                }

                ftpClient.readServerResponse();
            }

            ftpClient.binary();
            
return true;
        }
 catch (IOException e1) {
            e1.printStackTrace();
            
return false;
        }

    }


    
/**
     * 
     * 取得相對于當前連接目錄的某個目錄下所有文件列表
     * 
     * 
@param subPath
     *            連接目錄下的某個子目錄開始的路徑,如果是連接目錄則為空
     * 
@return List 返回的結果集合,對象類型為文件名稱的字符串
     * 
     
*/

    
public List<String> getFileList(String subPath) {
        
if(subPath==null || subPath.trim().length()<1{
            
return getFileList();
        }

        List
<String> list = new ArrayList<String>();
        BufferedReader  dis;
        
try {
            dis 
= new BufferedReader(new InputStreamReader(ftpClient.nameList(subPath),ftpClient.getEncoding()));
            String filename 
= "";
            
while ((filename = dis.readLine()) != null{
                list.add(filename);
            }

        }
 catch (IOException e) {
            e.printStackTrace();
        }

        
return list;
    }

    
/**
     * 
     * 取得相對于當前連接目錄的某個目錄下所有文件列表
     * 
     * 
@param subPath
     *            連接目錄下的某個子目錄開始的路徑,如果是連接目錄則為空
     * 
@return List 返回的結果集合,對象類型為文件名稱的字符串
     * 
     
*/

    
public List<String> getFileList() {
        List
<String> list = new ArrayList<String>();
        BufferedReader  dis;
        
try {
            dis 
= new BufferedReader(new InputStreamReader(ftpClient.list()));
            String filename 
= "";
            
while ((filename = dis.readLine()) != null{
                list.add(filename);
            }

        }
 catch (IOException e) {
            e.printStackTrace();
        }

        
return list;
    }

}