PhilW
PhilW

Reputation: 21

ftp_connect PHP Issues

I have a PHP script which connects to an external FTP server, and transfers 4 txt files across to the local server. One file is larger than others but they are generally a few hundred KB at the most. When it runs it sometimes fails, sometimes transfers partial files, sometimes one but not others. It never succeeds in transferring all.

Permissions have been checked and testing the FTP account manually shows that it is fine and connects and transfers smoothly and quickly. I've tried switching to ASCII but without success.

The account I'm connecting to with this script isn't SFTP, however the local server I'm transferring to is SFTP only (1&1). I'm not sure if that is relevant and wouldn't explain the intermittent nature. Thanks.

<?php

ini_set('display_errors', 1);

$ftp_server = "*";
$ftp_user_name = "*";
$ftp_user_pass = "*";

// define some variables
$local_file[0] = 'updates/vebraproperties.txt';
$local_file[1] = 'updates/files.txt';
$local_file[2] = 'updates/rooms.txt';
$local_file[3] = 'updates/vebraclients.txt';

$server_file[0] = 'vebraproperties.txt';
$server_file[1] = 'files.txt';
$server_file[2] = 'rooms.txt';
$server_file[3] = 'vebraclients.txt';

// set up basic connection
$conn_id = ftp_connect($ftp_server);

// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
echo $login_result . '<br/>'; 
for($i = 0; $i <= 3; $i++) {

    // try to download $server_file and save to $local_file
    if (ftp_get($conn_id, $local_file[$i], $server_file[$i], FTP_BINARY)) {
        echo "Successfully written to " . $local_file[$i] . "\n<br/>";
    } else {
        echo "There was a problem \n";
    }
}

// close the connection
ftp_close($conn_id);

?>

Upvotes: 2

Views: 325

Answers (2)

symcbean
symcbean

Reputation: 48387

FTP sucks. Really badly. You should be trying very hard to find a way of moving your files around without relying on it.

however the local server I'm transferring to is SFTP only (1&1)

Eh? That doesn't make any sense. SFTP is completely different when FTP. The ftp_ functions will not work with an "SFTP only" server. If it really is an SFTP server, then use the ssh2_sftp_ commands.

If it sometimes works and sometimes doesn't without changing the code, then the reason is not the code (which really makes the question off-topic here) but elsewhere (network, server).

Having said that, you do have some responsibility to make the code reasonably robust, e.g.

$login_result=false;
for ($x=0; $x<4 && !$login_result; $x++) {
   usleep($x*300);
   $conn_id = is_resource($conn_id) ? $conn_id : ftp_connect($ftp_server);
   $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
}

You didn't say what correlation existed between the status reported by your script and the outcome. The partial file thing is something of a concern. When dealing with transactional file transfers there are various options for ensuring the integrity of the transfer:

  • bundle the files up in a single entity which allows integrity verification (e.g. signed with PGP/GPG). This requires additional processing on the server
  • rename the files from the client when they are successfully uploaded (should be atomic and avoids the server from processing the file while its uploading) - note that many modern file transfer servers implement this server side - the target filename is not used until the data upload completes successfully.
  • put a lock file on the server to indicate a transfer is in process - remove it afterwards
  • put a semaphore file on the remote server when an upload completes successfully so the processing on the server knows that the file is available
  • use permissions to flag the state of the transfer

Upvotes: 0

jeroen
jeroen

Reputation: 91762

You could try using passive mode.

You can set that after logging in:

...
// Login
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
// Set passive mode
ftp_pasv($conn_id, true); 
...

Upvotes: 2

Related Questions