Kevin Mixon
Kevin Mixon

Reputation: 33

SFTP file is not downloaded completelly with ssh2.sftp and fread

I am working on a log file download for a separate system that requires SFTP for viewing logs. I am able to view the available log files on the server and download them. My issue is that it seems that the download stops at 2K which, in most cases, is only the first 10 lines of the log file. The files should contain thousands of lines as they are daily logs of changes made to the system.

I have done this in two separate files, one loads all of the files onto a page where the user can select the available log files and click a link to view the contents in the browser:

$ftp_server = "IP of Server";
$ftp_user_name = "USERNAME";
$ftp_user_pass = "PASSWORD";

$connection = ssh2_connect($ftp_server, 22); 
ssh2_auth_password($connection,$ftp_user_name, $ftp_user_pass);
$sftp = ssh2_sftp($connection); 

$dh = opendir("ssh2.sftp://$sftp//EMSftp/audit_files/"); 

while (($file = readdir($dh)) !== false) { 
    if ($file != '.' && $file != '..'){
        if (strpos($file,"2017-04")){
            echo '/EMSftp/audit_files/'.$file.' | <a href="open_file_curl.php?file='.$file.'" target="_blank">curl</a>
                                                | <a href="open_file.php?file='.$file.'" target="_blank">view</a><br>';
        }
    }
} 

closedir($dh);

I have tried to download the files two different ways using sftp and ssh2:

$file = $_GET['file'];
$local_file = "/var/www/uploads/logs/$file";

if (!file_exists($local_file)){
    $connection = ssh2_connect($ftp_server, 22); 
    ssh2_auth_password($connection,$ftp_user_name, $ftp_user_pass);
    $sftp = ssh2_sftp($connection); 

    $stream = @fopen("ssh2.sftp://$sftp//EMSftp/audit_files/$file", 'r');

    if (! $stream)
        throw new Exception("Could not open file: $remote_file");
    $contents = fread($stream, filesize("ssh2.sftp://$sftp//EMSftp/audit_files/$file"));            
    file_put_contents ($local_file, $contents);
    @fclose($stream);
}

echo '<pre>';
echo file_get_contents($local_file);
echo '</pre>';

and also tried to accomplish this using curl. This only creates a blank file. Not sure what is missing here. Unable to add the file contents to the file.

$file = $_GET['file'];

$local_file = "/var/www/uploads/logs/$file";

fopen($local_file, 'w+');
chmod($local_file, 0777);

$remote = "sftp://$ftp_user_name:$ftp_user_pass@$ftp_server//EMSftp/audit_files/$file";

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $remote);
curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
curl_setopt($curl, CURLOPT_USERPWD, "$ftp_user_name:$ftp_user_pass");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$somecontent = curl_exec($curl);
if (is_writable($local_file)) {

    if (!$handle = fopen($local_file, 'a')) {
         echo "Cannot open file ($local_file)";
         exit;
    }

    if (fwrite($handle, $somecontent) === FALSE) {
        echo "Cannot write to file ($local_file)";
        exit;
    }

    echo "Success, wrote ($somecontent) to file ($local_file)";

    fclose($handle);

} else {
    echo "The file $local_file is not writable";
}
curl_close($curl);

Not sure where I am missing something. Wondering if there is a time out related to this procedure that I am overlooking. Any help?

Upvotes: 3

Views: 1681

Answers (1)

Martin Prikryl
Martin Prikryl

Reputation: 202088

This is wrong:

$contents = fread($stream, filesize("ssh2.sftp://$sftp//EMSftp/audit_files/$file"));

It does not guarantee you, that a whole file will be read.

As documented:

fread() reads up to length bytes


If the logs are of reasonable size, use simple file_get_contents:

$contents = file_get_contents("ssh2.sftp://$sftp//EMSftp/audit_files/$file");

If not, read the file in chunks in a loop:

$stream = @fopen("ssh2.sftp://$sftp//EMSftp/audit_files/$file", 'r');

while (!feof($stream))
{
    $chunk = fread($stream, 8192);
    // write/append chunk to a local file
}

@fclose($stream);

Upvotes: 2

Related Questions