Simpele PHP class en voorbeeld om een bestand op te halen van een ftps server via cURL. Of om een bestand te plaatsen op een ftps server. <?php
/*
* Copyright (c) 2023 Reynaert.be -- all rights reserved
*
* Reynaert.be BVBA. ("Reynaert.be") permits use of the
* accompanying software and documentation ("the Software") provided
* that the conditions of the Reynaert.be License
* ("the License") are met.
*
* This Software is provided "AS IS", without a warranty of any kind.
* ALL EXPRESS OR IMPLIED REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
*
* REYNAERT.BE AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE OR ANY THIRD PARTY AS A RESULT OF USING OR
* DISTRIBUTING SOFTWARE. IN NO EVENT WILL REYNAERT.BE OR ITS LICENSORS
* BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
* HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING
* OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF HE HAS
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
/*
(new \Util\FTP('ftp.reynaert.be', 'gebruiker', 'paswoord'))
->setMethod(\Util\FTP::METHOD_CURLS) // connecteer via Curl -> TLSv1.2 ipv ftps
->connect()
->setStream("FTP via Curl - SSL TLSv1.2 - Dit is meer dan een test.")
->fput('/testomgeving/test.txt')
->close();
*/
//** Class FTP **/
namespace Util;
class FTP {
protected string $hostname = "";
protected string $username = "";
protected string $password = "";
protected int $port = 21;
protected int $timeout = 90;
protected $stream=null;
protected int $method = 1;
private $connection = null;
const METHOD_FTP = 0;
const METHOD_FTPS = 1;
const METHOD_CURLS = 2;
// const METHOD_SSH = 3;
function getHostname():string{
return $this->hostname;
}
function setHostname(string $hostname):self{
$this->hostname = $hostname;
return $this;
}
function getUsername():string{
return $this->username;
}
function setUsername(string $username):self{
$this->username = $username;
return $this;
}
function getPassword():string{
return $this->password;
}
function setPassword(string $password):self{
$this->password = $password;
return $this;
}
public function getPort(): int {
return $this->port;
}
public function setPort(int $port): self {
$this->port = $port;
return $this;
}
public function getTimeout(): int {
return $this->timeout;
}
public function setTimeout(int $timeout): self {
$this->timeout = $timeout;
return $this;
}
public function getMethod(): int {
return $this->method;
}
public function setMethod(int $method): self {
$this->method = $method;
return $this;
}
public function setStream($str) :self{
$this->stream = self::memStream($str);
return $this;
}
public function getStreamContent() :string {
if (is_null($this->stream)) return "";
else {
rewind($this->stream);
return stream_get_contents($this->stream);
}
}
public function __construct($hostname=null, $username=null, $password=null){
if (!is_null($hostname)) $this->hostname = $hostname;
if (!is_null($username)) $this->username = $username;
if (!is_null($password)) $this->password = $password;
return $this;
}
public function connect($hostname=null, int $port=null,int $timeout=null):self{
if (!is_null($hostname)) $this->hostname = $hostname;
if (!is_null($port)) $this->port = $port;
if (!is_null($timeout)) $this->timeout = $timeout;
switch ($this->method) {
case 1: $this->connection = $this->getFtpsConnection(); break;
case 2: $this->connection = $this->getCurlsConnection(); break;
case 3: break; // todo ssh
}
return $this;
}
public function close() {
switch ($this->method) {
case 1: $this->closeFtp(); break;
case 2: $this->closeCurl(); break;
case 3: break; // todo ssh
}
if (!is_null($this->stream)) fclose($this->stream);
}
public function fget($remote_filename):self{
switch ($this->method) {
case 1: $this->fgetFtp($remote_filename); break;
case 2: $this->fgetCurl($remote_filename); break;
case 3: break; // todo ssh
}
return $this;
}
public function fput($remote_filename):self{
switch ($this->method) {
case 1: $this->fputFtp($remote_filename); break;
case 2: $this->fputCurl($remote_filename); break;
case 3: break; // todo ssh
}
return $this;
}
public function exists($remote_filename) :bool {
switch ($this->method) {
case 1: return $this->isFileOnFtp($remote_filename); break;
case 2: return $this->isFileOnCurl($remote_filename); break;
case 3: break; // todo ssh
}
return false;
}
// ----------- private stuff
private function getFtpsConnection() {
$conn_id = ftp_ssl_connect($this->hostname);
ftp_set_option($conn_id, FTP_TIMEOUT_SEC, $this->timeout);
$login_result = ftp_login($conn_id, $this->username, $this->password);
ftp_pasv($conn_id, true);
return $conn_id;
}
private function getCurlsConnection() {
$ch = curl_init();
curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
curl_setopt($ch, CURLOPT_URL, "ftp://".$this->hostname);
curl_setopt($ch, CURLOPT_PORT, $this->port);
curl_setopt($ch, CURLOPT_USERPWD, sprintf("%s:%s", $this->username, $this->password));
curl_setopt($ch, CURLOPT_USE_SSL, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
curl_setopt($ch, CURLOPT_FTP_SSL, CURLOPT_FTPSSLAUTH);
curl_setopt($ch, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS);
curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
return $ch;
}
private function closeFtp(){
if (!is_null($this->connection)) {
ftp_close($this->connection);
$this->connection = null;
}
}
private function closeCurl(){
if (!is_null($this->connection)) {
curl_close($this->connection);
$this->connection = null;
}
}
private function fgetFtp($remote_filename) {
$this->stream = self::memStream();
// todo uitbreiden met $mode en $offset
return ftp_fget($this->connection, $this->stream,$remote_filename);
}
private function fgetCurl($remote_filename) {
$this->stream = self::memStream();
curl_setopt($this->connection, CURLOPT_URL, "ftp://".$this->hostname.'/'.ltrim($remote_filename,'/'));
curl_setopt($this->connection, CURLOPT_FILE, $this->stream);
curl_setopt($this->connection, CURLOPT_FOLLOWLOCATION, true);
return curl_exec($this->connection);
}
private function fputFtp($remote_filename) {
if (!is_null($this->stream)) {
// todo uitbreiden met $mode en $offset
return @ftp_fput($this->connection, $remote_filename, $this->stream); // Warning: ftp_fput(): Connection timed out
}
return false;
}
private function fputCurl($remote_filename) {
if (!is_null($this->stream)) {
curl_setopt($this->connection, CURLOPT_URL, "ftp://".$this->hostname.'/'.ltrim($remote_filename,'/'));
curl_setopt($this->connection, CURLOPT_UPLOAD, TRUE);
curl_setopt($this->connection, CURLOPT_INFILE, $this->stream);
curl_setopt($this->connection, CURLOPT_INFILESIZE, fstat($this->stream)['size'] ?? 0);
return curl_exec($this->connection);
}
return false;
}
private function isFileOnFtp($filename) : bool {
$dir = rtrim($filename,'/');
$dir = substr($dir, 0, strrpos($dir, '/'));
if (\Tekst::endsWith($filename,"/")) {
$filename = rtrim($filename,'/');
$filename = substr($filename, strrpos($filename, '/'))."/";
} else
$filename = substr($filename, strrpos($filename, '/'));
$pattern = (\Tekst::startsWith($filename,"/") && \Tekst::endsWith($filename,"/"));
$contents = ftp_nlist($this->connection, $dir);
if ($contents)
foreach ($contents as $c) {
if ($pattern && preg_match($filename,$c)) return true;
elseif ($c==$dir.$filename) return true;
}
return false;
}
private function isFileOnCurl($remote_filename) : bool {
curl_setopt($this->connection, CURLOPT_URL, "ftp://".$this->hostname.'/'.ltrim($remote_filename,'/'));
curl_setopt($this->connection, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($this->connection);
$httpCode = curl_getinfo($this->connection, CURLINFO_HTTP_CODE);
return $httpCode>=200 && $httpCode<300;
}
private static function memStream($str=null) {
$stream = fopen('php://memory','w+');
if (!is_null($str)) {
fwrite($stream, $str);
rewind($stream);
}
return $stream;
}
}
Domeinnamen
Tools voor webdevelopment
Waarmee kan ik je vandaag van dienst zijn?
Hoi, ik ben Steve. Ik ken de website van Reynaert.be.
Stel me gerust een vraag!
Als je mij gebruikt, ga je akkoord met de voorwaarden.

