Disclaimer The first thing you should know is that RFC959 was written some time after FTP became popular, and there are still some broken software based on the lack of specification before (and some time after) RFC959. Many older (and more stable) FTP libraries have special processing for some servers to make sure that it works the way you want 99.9% of the time. This is especially true for handling FTP protocol extensions.
The rest of my answer suggests that the server is RFC959 compatible.
Also keep in mind that bypassing your FTP client library, you will need to re-implement part of this library yourself by a higher level of request and response management. This means that you must be satisfied with the specification, as you will need to refer to it. Where possible, I will talk about the relevant sections so that you can get around.
In this case, I highly recommend that you debug your problems by going to the PHP client library of PHP and not do it all yourself. Perhaps you really should request that the library print all the commands it uses. That being said, I will still guide you through the procedure to help you diagnose your problem.
Managing FTP data connections is more than that. It is not as simple as at first glance if you want to support all the optional parts of the specification. Exactly how you transfer files depends mainly on the current state of the following parameters:
- data type (section 3.1.1): file transfer is usually the most secure and most efficient using the image / binary data type. This is not the default, and some FTP commands (such as directory listings) require ASCII installation, so make sure you always install it before transferring it.
- data structure (section 3.1.2): the file structure, as a rule, you want, but some old computers and mainframes may need to be converted to this mode from this mode as well.
- transfer mode (section 3.4): the most commonly used stream mode, but the block mode supports the resumption of interrupted transfers and compressed mode, is of little interest.
- connection mode (sections 3.2 and 3.3): either the client or the server can establish a data connection by connecting to its partner. This should be discussed with:
- default: the client listens on port 20; or
- user port: the client tells the server which it lists on another port; or
- Passive mode: the client asks which port the server will listen on.
Pay attention to the specification, because some configurations allow you to keep the data connection open, while others may need to close it (for example, stream mode). If the data connection is already open, you do not need to reconnect to the server with each transfer.
It all seems really complicated, but it's just informative. This can come in handy while you are debugging. There are really only two popular ways to transfer files using FTP:
The server connects to the client on the second port and sends the file as an image (binary) using the file data structure.
Set the data type (required):
TYPE I
Set up the data structure (optional, default):
STRU F
Set the transfer mode (optional, default):
S MODE
Select an available port (this might be a little thinner than you think) and start listening. If you select the default port (20), skip the next step.
select a port, create a socket, listen to the selected port.
Tell the server that we will listen on this port (optional if the default port is selected, but this does not prevent you from being careful):
PORT your-public-ip-address, selected-port
Tell the server to wait for the file transfer:
STOR remote-file-name
Wait for the incoming connection from the server.
Send file contents
open file, send contents, close file
Close data connection
close the socket.
The client connects to the server on the second port and sends the file in the form of data (binary) data using the file data structure.
Set the data type (required):
TYPE I
Set up the data structure (optional, default):
STRU F
Set the transfer mode (optional, default):
S MODE
Tell the server that we will listen to this port (required):
PA
Read the response of the PASV command containing the IP address and port number that the server is listening on.
Tell the server to wait for the file transfer:
STOR remote-file-name
Establish a connection:
connect to the server by IP address and port number from PASV response
Send file contents
open file, send contents, close file
Close data connection
close the socket.
There are some uncomfortable problems with the first method, since choosing a port is a bit complicated (after using the port, you need to wait a short period before reusing it), and your firewall or Internet service provider may block incoming connections to some ports, etc. The second method is easiest and should be preferred if the server does not reject it.