timothymarois timothymarois - 24 days ago 10
PHP Question

PHP upload via FTP - ftp_put() I won't open a connection to x.x.x.x (only to y.y.y.y)

I'm trying to use one host to upload content to another via FTP.

The "I won't open a connection to 172.xx.xx.xx (only to 54.xx.xx.xx)" is not even relevant because I am not connecting to that host. That's the IP address to the server that is hosting the script. But not to the server that is being accessed via FTP.

$conn_id = ftp_connect('50.xx.xx.xx');
ftp_pasv($conn_id, true);

$login_result = ftp_login($conn_id, 'user', 'pass');

$file = "http://domain.com/filelocation.swf";

if (ftp_put($conn_id, "test.swf", $file, FTP_BINARY)) {
echo 'File Uploaded';
}
else {
echo 'Problem with uploading';
}



ftp_put() I won't open a connection to 172.xx.xx.xx (only to 54.xx.xx.xx)


The IP addresses within this error, does not go to the server I am trying to connect to. The
ftp_login
connects and no issues. ( I don't even want it to make a connection to those IP addresses anyways, so why does it even think that?)

I can use
ftp_mkdir
to add a directory on the server. However, when I use
ftp_put
, it throws that error.

Answer

The error message is actually very relevant.

It's Pure-FTPd error response to PORT command, when the client is asking the server to open a data connection to an IP address different to that of the client (as the server sees it). So it's a remote error message sent by the server, not a local error message produced by PHP.

The problem is typically caused by the client knowing only its local IP address, not the external IP address.


Now, the question is why PHP uses PORT, when you asked it to connect using passive mode (ftp_pasv).

It's clearly because you call ftp_pasv before even logging in.

So the server rejects the PASV call with:

530 You aren't logged in

Unfortunately the PHP does not propagate error messages from PASV call. And it silently falls back to the default active mode. You can tell the call failed by its return value (that you do not check).


Just move the ftp_pasv call after the ftp_login.

$conn_id = ftp_connect('50.xx.xx.xx');

ftp_login($conn_id, 'user', 'pass');

ftp_pasv($conn_id, true);

The documentation clearly suggests it:

Please note that ftp_pasv() can only be called after a successful login or otherwise it will fail.


And of course, you should do a better error checking.

Comments