首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java FTPClient 實戰:Apache Commons Net 實現檔案上傳下載完整指南

     編輯:Java 相關知識

前言

FTP(File Transfer Protocol)是企業級應用中常見的檔案傳輸協定。Apache Commons Net 的 FTPClient 提供了完整的 FTP 客戶端功能。本文將通過完整代碼範例,展示如何實現檔案上傳、下載,並處理常見坑點。

一、Maven 依賴

<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.9.0</version> <!-- 請使用最新版本 -->
</dependency>

二、檔案上傳核心代碼

public boolean uploadFile(String host, int port, String username, String password,
                          String remotePath, String fileName, InputStream input) {
    FTPClient ftp = new FTPClient();
    try {
        // 1. 連線
        ftp.connect(host, port);
        if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
            ftp.disconnect();
            return false;
        }

        // 2. 登入
        ftp.login(username, password);

        // 3. 切換工作目錄(不存在需先建立)
        ftp.changeWorkingDirectory(remotePath);

        // 4. 設定傳輸模式:二進位模式(預設 ASCII 會損壞二進位檔)
        ftp.setFileType(FTP.BINARY_FILE_TYPE);

        // 5. 被動模式(穿透防火牆/NAT 必須)
        ftp.enterLocalPassiveMode();

        // 6. 上傳
        boolean success = ftp.storeFile(fileName, input);
        input.close();
        ftp.logout();
        return success;

    } catch (IOException e) {
        log.error("FTP 上傳失敗", e);
        return false;
    } finally {
        closeQuietly(ftp);
    }
}

private void closeQuietly(FTPClient ftp) {
    if (ftp != null && ftp.isConnected()) {
        try { ftp.disconnect(); } catch (IOException ignored) {}
    }
}

關鍵點說明

  • BINARY_FILE_TYPE:預設 ASCII 模式會破壞圖片、壓縮檔等二進位檔案,務必顯式設定。
  • enterLocalPassiveMode():主動模式需伺服器主動連回客戶端,防火牆通常阻擋;被動模式由客戶端發起所有連線,相容性最好。
  • 資源釋放:finally 區塊確保連線關閉,避免連線洩漏。

三、上傳場景範例

1. 本地檔案上傳

@Test
public void testUploadFromDisk() throws FileNotFoundException {
    try (FileInputStream in = new FileInputStream(new File("D:/test.txt"))) {
        boolean flag = uploadFile("127.0.0.1", 21, "user", "pass", "/ftp", "test.txt", in);
        System.out.println("上傳結果: " + flag);
    }
}

2. 字串內容上傳為檔案

@Test
public void testUploadFromString() throws UnsupportedEncodingException {
    InputStream input = new ByteArrayInputStream("測試 FTP 內容".getBytes("UTF-8"));
    boolean flag = uploadFile("127.0.0.1", 21, "user", "pass", "/ftp", "test.txt", input);
    System.out.println("上傳結果: " + flag);
}

四、檔案下載核心代碼

public boolean downloadFile(String host, int port, String username, String password,
                            String remotePath, String fileName, String localPath) {
    FTPClient ftp = new FTPClient();
    try {
        ftp.connect(host, port);
        if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
            ftp.disconnect();
            return false;
        }
        ftp.login(username, password);
        ftp.setFileType(FTP.BINARY_FILE_TYPE);
        ftp.enterLocalPassiveMode();
        ftp.changeWorkingDirectory(remotePath);

        // 列出檔案確認存在
        FTPFile[] files = ftp.listFiles();
        for (FTPFile file : files) {
            if (file.getName().equals(fileName)) {
                File localFile = new File(localPath + "/" + fileName);
                try (OutputStream os = new FileOutputStream(localFile)) {
                    return ftp.retrieveFile(fileName, os);
                }
            }
        }
        return false; // 找不到檔案
    } catch (IOException e) {
        log.error("FTP 下載失敗", e);
        return false;
    } finally {
        closeQuietly(ftp);
    }
}

五、進階建議

  • 連線池:高併發場景下,使用 PoolingFTPClientConnectionFactory + GenericObjectPool 管理連線池。
  • 斷點續傳:setRestartOffset() 支援斷點續傳大檔案。
  • FTPS 支援:需用 FTPSClient 替代 FTPClient,並配置 SSL/TLS 參數。
  • 編碼問題:中文檔名建議設定 ftp.setControlEncoding("UTF-8")。
  • 超時設定:ftp.setConnectTimeout(5000)、ftp.setDefaultTimeout(30000) 防止掛死。

六、總結

FTPClient 功能強大但細節多。掌握「二進位模式、被動模式、資源釋放」三大核心,能避開 90% 的坑。生產環境建議封裝為工具類,統一異常處理、日誌記錄、連線池管理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved