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

PHP FTP 函數完整教程:連線、上傳下載、目錄操作與非阻塞傳輸

     編輯:PHP 相關知識

FTP 擴展簡介

PHP FTP 擴展提供完整的 FTP 客戶端功能:連線認證、檔案上傳下載、目錄操作、權限修改、非阻塞傳輸、SSL/TLS 加密連線。Windows 版 PHP 內建,Linux 需編譯時加入 --enable-ftp。

安裝驗證

# Linux 編譯參數
./configure --enable-ftp

# 驗證
php -m | grep ftp
php -r "var_dump(function_exists('ftp_connect'));"

核心函數分類速查

連線與認證

函數說明
ftp_connect(host, port=21, timeout=90)建立 FTP 連線
ftp_ssl_connect(host, port=990, timeout=90)建立 SSL/TLS 加密連線 (FTPS)
ftp_login(conn, username, password)用戶認證
ftp_pasv(conn, true/false)開啟/關閉被動模式(穿透防火牆/NAT 必開)
ftp_close(conn)關閉連線
ftp_quit(conn)ftp_close 別名

目錄操作

函數說明
ftp_pwd(conn)取得當前目錄
ftp_chdir(conn, directory)切換目錄
ftp_cdup(conn)切換到上層目錄
ftp_mkdir(conn, directory)建立目錄
ftp_rmdir(conn, directory)刪除空目錄
ftp_nlist(conn, directory)列出目錄檔名陣列
ftp_rawlist(conn, directory)列出詳細資訊(含權限、大小、時間)

檔案操作

函數說明
ftp_put(conn, remote, local, mode)上傳檔案
ftp_fput(conn, remote, handle, mode)上傳開啟的檔案指標
ftp_get(conn, local, remote, mode)下載檔案
ftp_fget(conn, handle, remote, mode)下載到開啟的檔案指標
ftp_delete(conn, path)刪除檔案
ftp_rename(conn, old, new)重命名/移動
ftp_chmod(conn, mode, path)修改權限 (如 0644)
ftp_size(conn, path)取得檔案大小(位元組),失敗回 -1
ftp_mdtm(conn, path)取得最後修改時間 (Unix timestamp)
ftp_site(conn, command)發送 SITE 指令(伺服器專用)

傳輸模式常數

  • FTP_ASCII / FTP_TEXT:文本模式(換行轉換)
  • FTP_BINARY / FTP_IMAGE:二進制模式(圖片、壓縮檔、執行檔必須用此模式)

非阻塞傳輸(大檔案/斷點續傳核心)

函數說明
ftp_nb_put/get/fput/fget(...)啟動非阻塞傳輸
ftp_nb_continue(conn)繼續傳輸,回傳 FTP_MOREDATA/FTP_FINISHED/FTP_FAILED
FTP_AUTORESUME自動斷點續傳(配合 ftp_nb_get/put)

實戰範例

1. 基礎上傳下載封裝類

<?php
class FtpClient {
  private $conn;
  private $config;

  public function __construct(array $config) {
    $this->config = $config;
  }

  public function connect() {
    $this->conn = $this->config['ssl'] 
      ? @ftp_ssl_connect($this->config['host'], $this->config['port'] ?? 990, 30)
      : @ftp_connect($this->config['host'], $this->config['port'] ?? 21, 30);
    
    if (!$this->conn) throw new Exception("連線失敗: {$this->config['host']}");
    
    if (!@ftp_login($this->conn, $this->config['user'], $this->config['pass'])) {
      throw new Exception("認證失敗");
    }
    
    ftp_pasv($this->conn, true); // 被動模式
    return $this;
  }

  public function upload($localPath, $remotePath, $mode = FTP_BINARY) {
    return ftp_put($this->conn, $remotePath, $localPath, $mode);
  }

  public function download($remotePath, $localPath, $mode = FTP_BINARY) {
    return ftp_get($this->conn, $localPath, $remotePath, $mode);
  }

  public function delete($remotePath) {
    return ftp_delete($this->conn, $remotePath);
  }

  public function listFiles($dir = '.') {
    return ftp_nlist($this->conn, $dir);
  }

  public function __destruct() {
    if ($this->conn) @ftp_close($this->conn);
  }
}

// 使用
$ftp = new FtpClient([
  'host' => 'ftp.example.com',
  'user' => 'username',
  'pass' => 'password',
  'ssl'  => true, // FTPS
]);
$ftp->connect()->upload('local.jpg', '/remote/images/photo.jpg');
$ftp->download('/remote/backup.sql', 'backup.sql');

2. 非阻塞大檔案下載(含進度條邏輯)

<?php
function downloadLarge($ftp, $remote, $local) {
  $fp = fopen($local, 'w');
  $ret = ftp_nb_fget($ftp, $fp, $remote, FTP_BINARY, 0); // 0 = 從頭開始
  
  $total = ftp_size($ftp, $remote);
  $downloaded = 0;
  
  while ($ret === FTP_MOREDATA) {
    // 這裡可以更新進度條、寫入日誌、處理其他任務
    $downloaded = ftell($fp);
    echo "\r進度: " . round($downloaded/$total*100, 1) . "%";
    $ret = ftp_nb_continue($ftp);
  }
  
  fclose($fp);
  
  if ($ret !== FTP_FINISHED) {
    unlink($local); // 失敗刪除不完整檔案
    throw new Exception("下載失敗");
  }
  echo "\n下載完成\n";
}

3. 斷點續傳上傳

<?php
function uploadResume($ftp, $local, $remote) {
  $localSize = filesize($local);
  $remoteSize = ftp_size($ftp, $remote);
  
  if ($remoteSize >= $localSize) return true; // 已完成
  
  $fp = fopen($local, 'r');
  fseek($fp, $remoteSize); // 跳過已上傳部分
  
  $ret = ftp_nb_fput($ftp, $remote, $fp, FTP_BINARY, $remoteSize);
  
  while ($ret === FTP_MOREDATA) {
    $ret = ftp_nb_continue($ftp);
  }
  
  fclose($fp);
  return $ret === FTP_FINISHED;
}

常見問題與最佳實踐

問題解決方案
連線逾時/失敗檢查防火牆、確認主機支援被動模式、增加 ftp_connect timeout 參數
上傳檔案損壞/為 0 位元組二進制檔案必須用 FTP_BINARY 模式
中文檔名亂碼FTP 協議不規定編碼,建議檔名用 URL 編碼或 Base64,或確認伺服器支援 UTF-8 (RFC 2640)
權限不足無法建立目錄確認 FTP 用戶有寫入權限,或用 ftp_site($conn, 'CHMOD 755 dir')
長連線被伺服器斷開實作重連機制,或定期發送 ftp_pwd() 保持心跳

安全建議

  1. 優先使用 ftp_ssl_connect (FTPS) 或 SFTP (需 ssh2 擴展或 phpseclib)
  2. 避免在代碼中硬編碼密碼,使用環境變數或密碼管理器
  3. 限制 FTP 用戶權限:僅開放必要目錄,禁止 Shell 登入
  4. 記錄所有 FTP 操作日誌(IP、用戶、操作、檔案、結果)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved