FTP文件上傳與下載 – JAVA編程語言程序開發技術文章

實現FTP文件上傳與下載可以通過以下兩種種方式實現(不知道還有沒有其他方式,),分別為:1、通過JDK自帶的API實現;2、通過Apache提供的API是實現。
第一種方式
[java] 
package com.cloudpower.util; 
 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
 
import sun.net.TelnetInputStream; 
import sun.net.TelnetOutputStream; 
import sun.net.ftp.FtpClient; 
 
/**
 * Java自帶的API對FTP的操作
 * @Title:Ftp.java
 * @author: 周玲斌  
 */ 
public class Ftp { 
    /**
     * 本地文件名
     */ 
    private String localfilename; 
    /**
     * 遠程文件名
     */ 
    private String remotefilename; 
    /**
     * FTP客戶端
     */ 
    private FtpClient ftpClient; 
 
    /**
     * 服務器連接
     * @param ip 服務器IP
     * @param port 服務器端口
     * @param user 用戶名
     * @param password 密碼
     * @param path 服務器路徑
     * @author 周玲斌
     * @date   2012-7-11
     */ 
    public void connectServer(String ip, int port, String user, 
            String password, String path) { 
        try { 
            /* ******連接服務器的兩種方法*******/ 
            //第一種方法 
//            ftpClient = new FtpClient(); 
//            ftpClient.openServer(ip, port); 
            //第二種方法 
            ftpClient = new FtpClient(ip); 
             
            ftpClient.login(user, password); 
            // 設置成2進制傳輸 
            ftpClient.binary(); 
            System.out.println("login success!"); 
            if (path.length() != 0){ 
                //把遠程系統上的目錄切換到參數path所指定的目錄 
                ftpClient.cd(path); 
            } 
            ftpClient.binary(); 
        } catch (IOException ex) { 
            ex.printStackTrace(); 
            throw new RuntimeException(ex); 
        } 
    } 
    /**
     * 關閉連接
     * @author 周玲斌
     * @date   2012-7-11
     */ 
    public void closeConnect() { 
        try { 
            ftpClient.closeServer(); 
            System.out.println("disconnect success"); 
        } catch (IOException ex) { 
            System.out.println("not disconnect"); 
            ex.printStackTrace(); 
            throw new RuntimeException(ex); 
        } 
    } 
    /**
     * 上傳文件
     * @param localFile 本地文件
     * @param remoteFile 遠程文件
     * @author 周玲斌
     * @date   2012-7-11
     */ 
    public void upload(String localFile, String remoteFile) { 
        this.localfilename = localFile; 
        this.remotefilename = remoteFile; 
        TelnetOutputStream os = null; 
        FileInputStream is = null; 
        try { 
            //將遠程文件加入輸出流中 
            os = ftpClient.put(this.remotefilename); 
            //獲取本地文件的輸入流 
            File file_in = new File(this.localfilename); 
            is = new FileInputStream(file_in); 
            //創建一個緩沖區 
            byte[] bytes = new byte[1024]; 
            int c; 
            while ((c = is.read(bytes)) != -1) { 
                os.write(bytes, 0, c); 
            } 
            System.out.println("upload success"); 
        } catch (IOException ex) { 
            System.out.println("not upload"); 
            ex.printStackTrace(); 
            throw new RuntimeException(ex); 
        } finally{ 
            try { 
                if(is != null){ 
                    is.close(); 
                } 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } finally { 
                try { 
                    if(os != null){ 
                        os.close(); 
                    } 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
            } 
        } 
    } 
     
    /**
     * 下載文件
     * @param remoteFile 遠程文件路徑(服務器端)
     * @param localFile 本地文件路徑(客戶端)
     * @author 周玲斌
     * @date   2012-7-11
     */ 
    public void download(String remoteFile, String localFile) { 
        TelnetInputStream is = null; 
        FileOutputStream os = null; 
        try { 
            //獲取遠程機器上的文件filename,借助TelnetInputStream把該文件傳送到本地。 
            is = ftpClient.get(remoteFile); 
            File file_in = new File(localFile); 
            os = new FileOutputStream(file_in); 
            byte[] bytes = new byte[1024]; 
            int c; 
            while ((c = is.read(bytes)) != -1) { 
                os.write(bytes, 0, c); 
            } 
            System.out.println("download success"); 
        } catch (IOException ex) { 
            System.out.println("not download"); 
            ex.printStackTrace(); 
            throw new RuntimeException(ex); 
        } finally{ 
            try { 
                if(is != null){ 
                    is.close(); 
                } 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } finally { 
                try { 
                    if(os != null){ 
                        os.close(); 
                    } 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
            } 
        } 
    } 
 
    public static void main(String agrs[]) { 
 
        String filepath[] = { "/temp/aa.txt", "/temp/regist.log"}; 
        String localfilepath[] = { "C:\\tmp\\1.txt","C:\\tmp\\2.log"}; 
 
        Ftp fu = new Ftp(); 
        /*
         * 使用默認的端口號、用戶名、密碼以及根目錄連接FTP服務器
         */ 
        fu.connectServer("127.0.0.1", 22, "anonymous", "IEUser@", "/temp"); 
         
        //下載 
        for (int i = 0; i < filepath.length; i++) { 
            fu.download(filepath[i], localfilepath[i]); 
        } 
         
        String localfile = "E:\\號碼.txt"; 
        String remotefile = "/temp/哈哈.txt"; 
        //上傳 
        fu.upload(localfile, remotefile); 
        fu.closeConnect(); 
    } 

這種方式沒啥可說的,比較簡單,也不存在中文亂碼的問題。貌似有個缺陷,不能操作大文件,有興趣的朋友可以試試。
第二種方式
[java] 
public class FtpApche { 
    private static FTPClient ftpClient = new FTPClient(); 
    private static String encoding = System.getProperty("file.encoding"); 
    /**
     * Description: 向FTP服務器上傳文件
     * 
     * @Version1.0
     * @param url
     *            FTP服務器hostname
     * @param port
     *            FTP服務器端口
     * @param username
     *            FTP登錄賬號
     * @param password
     *            FTP登錄密碼
     * @param path
     *            FTP服務器保存目錄,如果是根目錄則為“/”
     * @param filename
     *            上傳到FTP服務器上的文件名
     * @param input
     *            本地文件輸入流
     * @return 成功返回true,否則返回false
     */ 
    public static boolean uploadFile(String url, int port, String username, 
            String password, String path, String filename, InputStream input) { 
        boolean result = false; 
 
        try { 
            int reply; 
            // 如果采用默認端口,可以使用ftp.connect(url)的方式直接連接FTP服務器 
            ftpClient.connect(url); 
            // ftp.connect(url, port);// 連接FTP服務器 
            // 登錄 
            ftpClient.login(username, password); 
            ftpClient.setControlEncoding(encoding); 
            // 檢驗是否連接成功 
            reply = ftpClient.getReplyCode(); 
            if (!FTPReply.isPositiveCompletion(reply)) { 
                System.out.println("連接失敗"); 
                ftpClient.disconnect(); 
                return result; 
            } 
 
            // 轉移工作目錄至指定目錄下 
            boolean change = ftpClient.changeWorkingDirectory(path); 
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE); 
            if (change) { 
                result = ftpClient.storeFile(new String(filename.getBytes(encoding),"iso-8859-1"), input); 
                if (result) { 
                    System.out.println("上傳成功!"); 
                } 
            } 
            input.close(); 
            ftpClient.logout(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } finally { 
            if (ftpClient.isConnected()) { 
                try { 
                    ftpClient.disconnect(); 
                } catch (IOException ioe) { 
                } 
            } 
        } 
        return result; 
    } 
 
    /**
     * 將本地文件上傳到FTP服務器上
     * 
     */ 
    public void testUpLoadFromDisk() { 
        try { 
            FileInputStream in = new FileInputStream(new File("E:/號碼.txt")); 
            boolean flag = uploadFile("127.0.0.1", 21, "zlb","123", "/", "哈哈.txt", in); 
            System.out.println(flag); 
        } catch (FileNotFoundException e) { 
            e.printStackTrace(); 
        } 
    } 
 
 
    /**
     * Description: 從FTP服務器下載文件
     * 
     * @Version1.0
     * @param url
     *            FTP服務器hostname
     * @param port
     *            FTP服務器端口
     * @param username
     *            FTP登錄賬號
     * @param password
     *            FTP登錄密碼
     * @param remotePath
     *            FTP服務器上的相對路徑
     * @param fileName
     *            要下載的文件名
     * @param localPath
     *            下載後保存到本地的路徑
     * @return
     */ 
    public static boolean downFile(String url, int port, String username, 
            String password, String remotePath, String fileName, 
            String localPath) { 
        boolean result = false; 
        try { 
            int reply; 
            ftpClient.setControlEncoding(encoding); 
             
            /*
             *  為瞭上傳和下載中文文件,有些地方建議使用以下兩句代替
             *  new String(remotePath.getBytes(encoding),"iso-8859-1")轉碼。
             *  經過測試,通不過。
             */ 
//            FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT); 
//            conf.setServerLanguageCode("zh"); 
 
            ftpClient.connect(url, port); 
            // 如果采用默認端口,可以使用ftp.connect(url)的方式直接連接FTP服務器 
            ftpClient.login(username, password);// 登錄 
            // 設置文件傳輸類型為二進制 
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); 
            // 獲取ftp登錄應答代碼 
            reply = ftpClient.getReplyCode(); 
            // 驗證是否登陸成功 
            if (!FTPReply.isPositiveCompletion(reply)) { 
                ftpClient.disconnect(); 
                System.err.println("FTP server refused connection."); 
                return result; 
            } 
            // 轉移到FTP服務器目錄至指定的目錄下 
            ftpClient.changeWorkingDirectory(new String(remotePath.getBytes(encoding),"iso-8859-1")); 
            // 獲取文件列表 
            FTPFile[] fs = ftpClient.listFiles(); 
            for (FTPFile ff : fs) { 
                if (ff.getName().equals(fileName)) { 
                    File localFile = new File(localPath + "/" + ff.getName()); 
                    OutputStream is = new FileOutputStream(localFile); 
                    ftpClient.retrieveFile(ff.getName(), is); 
                    is.close(); 
                } 
            } 
 
            ftpClient.logout(); 
            result = true; 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } finally { 
            if (ftpClient.isConnected()) { 
                try { 
                    ftpClient.disconnect(); 
                } catch (IOException ioe) { 
                } 
            } 
        } 
        return result; 
    } 
 
    /**
     * 將FTP服務器上文件下載到本地
     * 
     */ 
    public void testDownFile() { 
        try { 
            boolean flag = downFile("127.0.0.1", 21, "zlb", 
                    "123", "/", "哈哈.txt", "D:/"); 
            System.out.println(flag); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    } 
     
    public static void main(String[] args) { 
        FtpApche fa = new FtpApche(); 
        fa.testDownFile(); 
    } 

這種方式的話需要註意中文亂碼問題啦,如果你設置不恰當,有可能上傳的文件名會為亂碼,有的時候根本就上傳不上去,當然,也不會跟你提示,因為原本就沒異常。在網上找瞭好多解答方案,眾說紛紜,幾乎都是從一個版本拷貝過去的,也沒有經過自己的真是檢驗。為此,也吃瞭不少苦頭。大致分為以下兩種解決方案:
1、加上以下三句即可解決
ftpClient.setControlEncoding(“GBK”);
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
conf.setServerLanguageCode("zh");
解答:經過測試,根本上行不通,上述問題依然存在
2、與上述方式有所類似,但我覺得這種方式更靠譜一點
首先,加上ftpClient.setControlEncoding(“GBK”);這一句,然後,將所有的中文進行轉碼為“ISO-8859-1”格式,如下:
ftpClient.changeWorkingDirectory(new String(remotePath.getBytes("GBK"),"iso-8859-1"));
解答:經過測試,仍然行不通,之所以我說此方式更靠譜一點,請繼續往下看
首先我們來說說為什麼要進行轉碼:
因為在FTP協議裡面,規定文件名編碼為iso-8859-1,所以目錄名或文件名需要轉碼。
接下來的問題是,我們應該將什麼編碼轉換為此格式。因此,就有瞭第二種解決方案——把GBK格式的轉換為ISO-8859-1格式。而且,有的人還說,必須得這麼轉。其實,之所以他們能這麼說,我覺得完全是巧合。它的真正原理是,既然FTP協議規定的編碼格式是“ISO-8859-1”,那麼我們確實得將格式轉換一下,然後等服務器收到文件時再自動轉換為系統自帶的編碼格式,因此,關鍵不是規定為什麼格式,而是取決於FTP服務器的編碼格式。因此,如果FTP系統的編碼格式為“GBK”時,第二種方式肯定會成功;但是,如果系統的編碼格式為“UTF-8”時,那就會仍然出現亂碼啦。所以,我們隻能通過代碼先獲取系統的編碼格式,然後通過此編碼格式轉換為ISO-8859-1的編碼格式。獲取方式如下:
private static String encoding = System.getProperty("file.encoding");
作者:zlb824

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。