1. 程式人生 > >使用Apache Commons Net API實現FTP上傳下載過程中的坑點

使用Apache Commons Net API實現FTP上傳下載過程中的坑點

       最近專案需要實現FTP上傳、下載功能,採用了Apache Commons Net API。程式碼很快就完成了,但由於對相關API使用場景不是很熟悉,走了一些彎路,抽一點時間做一下總結。

        A)主動被動模式選擇:FTP主動模式和被動模式的詳細介紹可以參考(http://blog.csdn.net/huanggang028/article/details/41248663)。大概意思就是主動模式是客戶端向服務端傳送PORT命令,然後服務端通過20資料埠連線客戶端開啟的埠,然後傳送資料;被動模式是客戶端向服務端傳送PASV命令,服務端隨機開啟一個埠並通知客戶端,客戶端根據該埠與服務端建立連線,然後傳送資料。服務端是兩種模式的,使用哪種模式取決於客戶端,同時關鍵點在於網路環境適合用哪種模式,比如客戶端在防火牆內,則最好選擇被動模式。

ftpClient.enterLocalActiveMode()便是配置成主動模式,而ftpClient.enterLocalPassiveMode()則配置成被動模式。

        B)檔案格式選擇:預設是型別是ASCII(普通文字檔案),但是為了使得支援任何型別,建議設定成BINARY_FILE_TYPE,並且是在上傳和下載操作開始前呼叫setFileType(int fileType)

       C)上傳、下載過載方法的使用選擇:比如上傳,boolean storeFile(String remote, InputStream local)OutputStream storeFileStream(String remote)

,差別是第一個方法如果我們不用關心到底已經從InputStream中傳遞了多少位元組,完全依靠介面內部實現完成輸入輸出操作,而第二個方法使得我們可以在上傳過程中控制傳送位元組速度等額外操作,比如傳送進度的實現便可以依賴此方法。但是,需要注意的是,如果採用了第二個方法來做, 必須靠我們去實現是否上傳完畢、下載完畢的事後控制,否則會出現問題。比如我們採用第二個方法,需要手動關閉流,同時,緊接著呼叫completePendingCommand()方法。如果使用第一個方法不能呼叫completePendingCommand()方法,因為它一旦被呼叫, 會一直等待FTP伺服器返回226Transfer complete
,但是FTP伺服器只有在接受流執行close方法時,才會返回。不該呼叫的時候呼叫了便會出現僵死現象,同時報錯:

<span style="font-size:18px;">    14/11/19 13:43:29 ERROR expand.FTPSupport: FTP response 421 received.  Server closed connection.
org.apache.commons.net.ftp.FTPConnectionClosedException: FTP response 421 received.  Server closed connection.
at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:363)
at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:290)
at org.apache.commons.net.ftp.FTP.getReply(FTP.java:637)
at org.apache.commons.net.ftp.FTPClient.completePendingCommand(FTPClient.java:1637)</span>

同時自己通過判斷in.read()!=-1作為檔案結束,存在有時不同作業系統結束符有問題, 然後採用Apache common的IOUitls類解決。