ab_dev86
ab_dev86

Reputation: 1982

fopen via ssh doesn't retrieve the entire file

I have to open a file with fopen and read the entire content. The file is accessible through a ssh-sftp connection:

Here is my code to connect, open and read the file:

//ssh connection
$connection = ssh2_connect($host, $port);
//open the file
$handle = fopen("ssh2.sftp://$sftp".$file, "r");
$out = array();
//read the file
while (($fields = fgetcsv($handle, 0, ";")) !== FALSE) {
   $out[]=$fields;
}

The file is actually a csv one. With fgetcsv I read the file row by row. But even if my file has let's say 50 rows after about 20 rows the fgetcsv fails and my final out array is incomplete. The file is actually local on my machine: if opened through ssh only the first 20 rows are read, if opened normally with a direct file system path:

fopen("localpath", "r");

The while loop reads all the 50 rows.

Is there any limit in bytes when reading from a ssh connection? Can this limit be changed with a php.ini configuration option?

Upvotes: 0

Views: 4053

Answers (3)

ab_dev86
ab_dev86

Reputation: 1982

I'm answering my own question in order to clarify exactly the problem:

I run linux red hat entrprise 6.0 with php 5.1. I managed to solve the problem: actually the remote file i was trying to access is created, behind the scenes, before my fopen runs. the "behind the scenes" code uses fread to create the file (reading from another original file). With php 5.1 fread shows this bug bugs.php.net/bug.php?id=35859&edit=2: a limit of 8k when reading a file. So after that in can access the file in many ways but still its size is 8k and the other content is lost.

Upvotes: 0

neubert
neubert

Reputation: 16782

My recommendation: try phpseclib, a pure PHP SFTP implementation. eg.

<?php
include('Net/SFTP.php');

$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
    exit('Login Failed');
}

$csv = $sftp->get('filename.ext');

$handle = fopen('php://memory', 'r+');
fputs($handle, $csv);
rewind($handle);

while (($fields = fgetcsv($handle, 0, ";")) !== FALSE) {
   $out[]=$fields;
}
?>

Even if it doesn't work (and I think there's a good chance it would) phpseclib supports logging so you can see exactly where it's messing up. Like maybe it's an issue with your SSH server and you're getting an SSH packet back that says "server doesn't support sending out files larger than 8k". If that was the case libssh2 wouldn't tell you whereas phpseclib could (well, if you enable logging, which isn't enabled by default).

Anyway, just try that. I'll help you out from there if you need it!

Upvotes: 3

rkosegi
rkosegi

Reputation: 14618

Try to fetch entire file using file_get_contents() and then do parsing of CSV data.

Upvotes: 1

Related Questions