まず、コードを php ファイルの一番上 (インクルードの前でも) に配置することを強くお勧めしますset_time_limit(0);
。これは、どれだけの時間がかかるかわからない操作を扱っているためです。
これは、Webサーバー/ブラウザが「長い」期間にわたってデータを送受信しないことでタイムアウトになった場合だと思います. これを修正するには、SFTP.php ファイル、つまり Net_SFTP クラスを少し変更し、get メソッド (phpseclib 0.3.1 の場合は 1482 行目) に移動し、唯一の "while" 制御構造内に何かを追加する必要があります。そこに (関数全体を下に貼り付けます)、次のコードを追加します。
if (strtolower(PHP_SAPI) != 'cli') { // run this if request is handled by a webserver (like your case)
$my_iter++;
if($my_iter > 1024){
$my_iter = 0; // reset the counter
echo "transferring ... " . date("G:i:s") . "<br />"; // send something to the buffer
}
// flush the buffers and prevent the timeout by actually outputting something to the browser
ob_end_flush();
ob_flush();
flush();
ob_start();
usleep(100); // just in case, try removing this delay
}
これは基本的に時々何かを出力し (この間の 1024 回の反復)、実際にブラウザーに何かを出力するためにバッファーをフラッシュします。値を自由に調整してください。これらの問題のため、これは Web サーバーから実行することを意図していないコード (SFTP クラス) です。つまり、できますが、このようないくつかの問題に遭遇します。
また、send() を試みる場合は、対応するメソッドで同様の変更を行う必要がありますが、これで問題が解決されることを願っています (少なくとも、これで私のローカル開発ボックスでのタイムアウトの問題が修正されました)。
ここで、約束どおり、メソッドの完全な変更を以下に示します ;-)
function get($remote_file, $local_file = false)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
return false;
}
$remote_file = $this->_realpath($remote_file);
if ($remote_file === false) {
return false;
}
$packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_READ, 0);
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
return false;
}
$response = $this->_get_sftp_packet();
switch ($this->packet_type) {
case NET_SFTP_HANDLE:
$handle = substr($response, 4);
break;
case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
$this->_logError($response);
return false;
default:
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS', E_USER_NOTICE);
return false;
}
if ($local_file !== false) {
$fp = fopen($local_file, 'wb');
if (!$fp) {
return false;
}
} else {
$content = '';
}
$read = 0;
while (true) {
if (strtolower(PHP_SAPI) != 'cli') { // run this if request is handled by a webserver (like your case)
$my_iter++;
if($my_iter > 1024){
$my_iter = 0; // reset the counter
echo "transferring ... " . date("G:i:s") . "<br />"; // send something to the buffer
}
// flush the buffers and prevent the timeout by actually outputting something to the browser
ob_end_flush();
ob_flush();
flush();
ob_start();
usleep(100); // just in case, try removing this delay
}
$packet = pack('Na*N3', strlen($handle), $handle, 0, $read, 1 << 20);
if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
if ($local_file !== false) {
fclose($fp);
}
return false;
}
$response = $this->_get_sftp_packet();
switch ($this->packet_type) {
case NET_SFTP_DATA:
$temp = substr($response, 4);
$read+= strlen($temp);
if ($local_file === false) {
$content.= $temp;
} else {
fputs($fp, $temp);
}
break;
case NET_SFTP_STATUS:
$this->_logError($response);
break 2;
default:
user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS', E_USER_NOTICE);
if ($local_file !== false) {
fclose($fp);
}
return false;
}
}
if ($local_file !== false) {
fclose($fp);
}
if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle))) {
return false;
}
$response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) {
user_error('Expected SSH_FXP_STATUS', E_USER_NOTICE);
return false;
}
$this->_logError($response);
// check the status from the NET_SFTP_STATUS case in the above switch after the file has been closed
if ($status != NET_SFTP_STATUS_OK) {
return false;
}
if (isset($content)) {
return $content;
}
return true;
}