Search code examples
phpsslftpftps

PHP attempting FTPS transfer creates empty files


I'm currently attempting to use PHP to transfer small files between our server and a remote FTPS (FTP over SSL) server. I'm the standard fair to get this done, ie, file_put_contents, file_get_contents, etc... with the following stream context:

stream_context_create(array('ftp' => array('overwrite' => true), 'ssl' => array('allow_self_signed' => true)))

I'm passing this context stream using the following code. It can connect to the FTPS server just fine, but when it comes to creating the remote file, the file itself completely empty. Empty as in 0 for the file size.

    if(false === file_exists($localFile))
    {
        throw new Exception("Local file, {$localFile}, does not exist.");
    }

    if(false === $localFileContents = file_get_contents($localFile))
    {
        throw new Exception("Could not open Local file, {$localFile}.");
    }

    if(false === file_put_contents("{$this->url}{$remoteFile}", $localFileContents, FILE_APPEND, $this->context))
    {
        throw new Exception("Could not write to remote file, {$remoteFile}.");
    }

The remote file location, ie $this->url, is in the following format: "ftps://{user}:{pass}@{host}:{port}"

We're currently using Windows/Apache setup, so I can't use ftp_ssl_connect() without compiling our own PHP binaries. We couldn't go this route anyhow as it's a major change in our environment.


Solution

  • I've just had to do something very similiar.

    I found the solution here: http://www.php.net/manual/en/function.curl-setopt.php#90988

    I ended up wrapping it in a class thusly:

    class ftps {
    
        /**
         * @param string $remoteDir Fully quantified path to the directory, eg ftp://foo:[email protected]/directory/
         */
        public function ls($remoteDir) {
    
            $connection = $this->initConnection();
    
            curl_setopt_array($connection, array(
                CURLOPT_URL => $remoteDir,
                CURLOPT_RETURNTRANSFER => 1
            ));
    
            $result = curl_exec($connection);
    
            $this->finishConnection($connection);
    
            return explode("\n", $result);
    
        }
    
        private function initConnection()
        {
            $connection = curl_init();
    
            curl_setopt_array($connection, array(
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_SSL_VERIFYHOST => false,
                CURLOPT_FTP_SSL => CURLFTPSSL_TRY
            ));
    
            return $connection;
        }
    
        private function finishConnection(&$connection)
        {
            curl_close($connection);
            unset($connection);
        }
    
    }