我正在使用PHPSecLib的SFTP功能从FTP服务器下载文件。
该行
$sftp->get($fname);
如果文件高达200MB,则有效;如果文件高达200MB,则浏览器会响应“Firefox无法在[download.php]找到该文件”。也就是说,它说找不到我用来下载远程文件的php文件。
起初我认为这是由于php.ini中的memory_limit
设置,但是如果它设置为128M或350M并不重要; 200MB文件仍然有效,300MB文件失败。它在十秒后失败,因此max_execution_time
或max_input_time
似乎不是罪魁祸首。可能有什么不对?
答案 0 :(得分:1)
首先,我强烈建议您将代码set_time_limit(0);
放在php文件的最顶层(甚至在任何包含之前),因为您正在处理操作,您不知道他们有多少时间将采取。
我想说这是网络服务器/浏览器在“很长”的时间内没有发送/接收任何数据的时间。要解决这个问题,我们必须改变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类)。我的意思是,你可以,但你会遇到一些问题,比如这个问题。
此外,如果你尝试发送(),你将不得不对相应的方法进行类似的修改,但希望这将涵盖你的问题(至少这解决了我的本地开发盒上的超时问题)。 / p>
现在,完整的方法修改如下所示: - )
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;
}
答案 1 :(得分:1)
你可以做的其他事情......
<?php
include('Net/SFTP.php');
$sftp = new Net_SFTP('www.domain.tld');
$sftp->login('username', 'password');
$start = 0;
while (true) {
$response = $sftp->get('1mb', false, $start, 1024);
$start+= 1024;
if (empty($response)) {
break;
}
echo $response;
}
即。以多个块下载文件。