在 Java 應用程式中需要自動化上傳/下載檔案至 FTP 伺服器時,除了 Apache Commons Net 這類成熟函式庫,JDK 內建的 sun.net.ftp.FtpClient (位於 rt.jar) 也是一個零依賴的輕量選項。雖然屬於非標準 API (Sun 專有),但在 JDK 8/11 等主流版本中均可使用。本文示範如何封裝該類別完成連線、登入、目錄切換、檔案上傳下載與列表操作。
| 方法 | 說明 |
|---|---|
FtpClient(String host) | 建立連線至指定主機 (Port 21) |
login(String user, String pass) | 使用者認證 |
binary() / ascii() | 設定傳輸模式 (二進位/文字) |
cd(String dir) | 切換遠端工作目錄 |
cdUp() | 回上層目錄 |
pwd() | 取得目前遠端目錄路徑 |
list() | 取得目錄列表 TelnetInputStream |
get(String filename) | 下載檔案,回傳 TelnetInputStream |
put(String filename) | 上傳檔案,回傳 TelnetOutputStream |
rename(String from, String to) | 重新命名遠端檔案/目錄 |
closeServer() | 關閉連線 |
import java.io.*;
import sun.net.ftp.FtpClient;
import sun.net.TelnetInputStream;
import sun.net.TelnetOutputStream;
public class FtpClientDemo {
public static void main(String[] args) {
String host = "ftp.example.com";
String user = "username";
String pass = "password";
String remoteDir = "/upload";
String localFile = "D:/data/report.pdf";
String remoteFile = "report.pdf";
try (FtpClient ftp = new FtpClient(host)) {
// 1. 登入
ftp.login(user, pass);
System.out.println("登入成功,目前目錄: " + ftp.pwd());
// 2. 設定二進位模式 (預設即為 binary,但明確呼叫較佳)
ftp.binary();
// 3. 切換目錄
ftp.cd(remoteDir);
System.out.println("切換至: " + ftp.pwd());
// 4. 上傳檔案
try (FileInputStream fis = new FileInputStream(localFile);
TelnetOutputStream tos = ftp.put(remoteFile)) {
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) != -1) {
tos.write(buffer, 0, len);
}
tos.flush();
System.out.println("上傳完成: " + remoteFile);
}
// 5. 列出目錄內容
System.out.println("--- 目錄列表 ---");
try (TelnetInputStream tis = ftp.list();
BufferedReader br = new BufferedReader(new InputStreamReader(tis, "UTF-8"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
// 6. 下載檔案 (示範下載剛上傳的檔案)
String downloadPath = "D:/download/" + remoteFile;
try (TelnetInputStream tis = ftp.get(remoteFile);
FileOutputStream fos = new FileOutputStream(downloadPath)) {
byte[] buffer = new byte[8192];
int len;
while ((len = tis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("下載完成: " + downloadPath);
}
} catch (IOException e) {
System.err.println("FTP 操作失敗: " + e.getMessage());
e.printStackTrace();
}
}
}
TelnetInputStream 讀取目錄列表時,預設可能為 ISO-8859-1,中文檔名需手動轉碼:new String(bytes, "ISO-8859-1").getBytes("UTF-8") 或指定 InputStreamReader(tis, "GBK") (視 Server 設定)。FtpClient 內部預設使用被動模式 (PASV),若 Server 防火牆限制被動 Port 範圍,可能導致資料連線失敗。此類別不支援手動切換主動模式。sun.* 套件不保證跨 JDK 版本相容,長期專案建議改用 Apache Commons Net (FTPClient) 或 JSch (SFTP)。實務上建議將上述邏輯封裝為 FtpService 介面與實作類,支援:
GenericObjectPool)。sun.net.ftp.FtpClient 雖然輕量零依賴,但功能有限且非標準。適合簡單的內部工具、測試腳本或受限環境。企業級應用請優先選用成熟開源函式庫,獲得更完善的協定支援、安全性與維護保障。