應該注意的是,ftp_pasv 必須在 ftp_login 之後呼叫(而不是在 ftp_connect 之後)。對許多人來說可能很明顯,但我花了三個小時才發現...
(PHP 4, PHP 5, PHP 7, PHP 8)
ftp_pasv — 開啟或關閉被動模式
ftp_pasv() 開啟或關閉被動模式。在被動模式中,資料連線由用戶端而非伺服器發起。如果用戶端位於防火牆後方,可能需要此模式。
請注意,ftp_pasv() 只能在成功登入後呼叫,否則將會失敗。
版本 | 說明 |
---|---|
8.1.0 | 參數 ftp 現在預期一個 FTP\Connection 實例;先前預期一個 資源。 |
範例 #1 ftp_pasv() 範例
<?php
$file = 'somefile.txt';
$remote_file = 'readme.txt';
// 設定基本連線
$ftp = ftp_connect($ftp_server);
// 使用使用者名稱和密碼登入
$login_result = ftp_login($ftp, $ftp_user_name, $ftp_user_pass);
// 開啟被動模式
ftp_pasv($ftp, true);
// 上傳檔案
if (ftp_put($ftp, $remote_file, $file, FTP_ASCII)) {
echo "成功上傳 $file\n";
} else {
echo "上傳 $file 時發生問題\n";
}
// 關閉連線
ftp_close($ftp);
?>
應該注意的是,ftp_pasv 必須在 ftp_login 之後呼叫(而不是在 ftp_connect 之後)。對許多人來說可能很明顯,但我花了三個小時才發現...
對於某些 FTP 伺服器,被動和其他命令的順序似乎比其他 FTP 伺服器更重要。抱歉,我不知道具體的供應商或版本。
<?php
ftp_pasv($handle, true);
echo "系統類型: ".ftp_systype($handle).PHP_EOL;
ftp_fput($handle, 'example.txt', $stream, FTP_BINARY);
?>
> PHP 警告:ftp_fput(): STOR 順序錯誤。
<?php
echo "系統類型: ".ftp_systype($handle).PHP_EOL;
ftp_pasv($handle, true);
ftp_fput($handle, 'example.txt', $stream, FTP_BINARY);
?>
> 沒有問題
如果您在 Windows 上以被動模式執行 FileZilla,並嘗試使用 PHP 連線,您可能會遇到錯誤,顯示「425 無法開啟資料連線以傳輸 ...」。
此錯誤並非表示被動模式問題,但可以使用以下方式解決
<?php
ftp_pasv($conn, true);
?>
如果在選擇 ftp_pasv() 之後仍然遇到問題,您應該在傳輸 x 個檔案和/或 y GB 後,透過 ftp_close() / ftp_connect() 重新整理連線。
它解決了幾個(隨機)發生的問題,例如
ftp_get(): 開啟二進位模式資料連線
ftp_get(): 進入被動模式
提示:fopen() 建立了一個檔案,因此如果發生錯誤,別忘了刪除它;)
我發現有一個地方需要被動模式才能正常運作,但初始錯誤以奇怪的方式顯現出來
PHP 警告:ftp_put():在 <file.php> 的第 <#> 行中,TYPE 現在是 ASCII
或
PHP 警告:ftp_put():在 <file.php> 的第 <#> 行中,TYPE 現在是 8 位元二進位
另一個症狀是花費很長的時間,可能長達設定的 90 秒逾時時間。連線時沒有發生錯誤,只有在嘗試 ftp_put() 時才會發生。
一旦我開啟 ftp_pasv(),它就開始運作了,無論是在主動模式可以運作的地方,還是在主動模式無法運作的伺服器上。
直接取自 bsd FTP 手冊頁面
PASV 命令請求遠端伺服器開啟一個用於資料連線的連接埠,並回傳該連接埠的位址。遠端伺服器會監聽該連接埠,而用戶端會連線到該連接埠。
當使用較傳統的 PORT 命令時,用戶端會監聽一個連接埠,並將該位址傳送給遠端伺服器,然後遠端伺服器會回連到該位址。當透過控制流量方向的閘道路由器或主機使用 FTP 時,被動模式非常有用。(請注意,雖然 RFC 1123 要求 FTP 伺服器必須支援 PASV 命令,但有些伺服器並未支援。)