ftp_fget()
La funzione ftp_fget() è una funzione PHP integrata che scarica un file remoto dal server FTP e lo salva in un file handle locale già aperto.
Cos'è ftp_fget()?
ftp_fget() scarica un file da un server FTP e lo scrive in un file handle locale già aperto. Questa è la differenza fondamentale rispetto a ftp_get(): ftp_get() accetta un percorso locale e crea il file per te, mentre ftp_fget() accetta una risorsa file aperta (il valore restituito da fopen()). Poiché gestisci direttamente l'handle, ftp_fget() è utile quando vuoi scrivere in uno stream che non è un semplice file — uno stream temporaneo (php://temp), un buffer in memoria, o un handle posizionato con fseek().
Questa pagina tratta la firma della funzione, un download funzionante completo, come scegliere la modalità di trasferimento, come riprendere un download interrotto e la gestione degli errori necessaria nel codice reale.
L'estensione FTP procedurale fa ancora parte di PHP. A partire da PHP 8.1 la connessione è un oggetto
FTP\Connectionanziché unaresource, ma il codice che scrivi rimane invariato. Per i trasferimenti cifrati usaftp_ssl_connect()al posto diftp_connect().
Sintassi di ftp_fget()
ftp_fget(
FTP\Connection $ftp,
resource $stream,
string $remote_filename,
int $mode = FTP_BINARY,
int $offset = 0
): bool| Parametro | Descrizione |
|---|---|
$ftp | La connessione restituita da ftp_connect() (e autenticata con ftp_login()). |
$stream | Un puntatore a file locale aperto in cui vengono scritti i dati scaricati. Deve essere aperto in scrittura ('w', 'w+', 'a', ecc.). |
$remote_filename | Percorso del file sul server FTP. |
$mode | Modalità di trasferimento: FTP_BINARY (impostazione predefinita da PHP 7.3) per qualsiasi file non testuale, oppure FTP_ASCII per testo normale con normalizzazione dei fine riga. |
$offset | Posizione in byte nello stream locale da cui iniziare a scrivere — usata per riprendere un download parziale. Il valore predefinito è 0. |
Restituisce true in caso di successo e false in caso di fallimento.
Scaricare un file con ftp_fget()
Un download completo prevede quattro passaggi: connettiti, accedi, apri un handle locale, poi scarica. Chiudi sempre sia l'handle che la connessione al termine.
<?php
// 1. Connect (returns false on failure)
$ftp = ftp_connect('ftp.example.com');
if ($ftp === false) {
exit("Could not connect to the FTP server.\n");
}
// 2. Authenticate
if (!ftp_login($ftp, 'username', 'password')) {
exit("FTP login failed.\n");
}
// Most networks need passive mode so the data channel works behind NAT/firewalls
ftp_pasv($ftp, true);
// 3. Open a local handle for writing
$handle = fopen('downloads/report.pdf', 'w');
// 4. Download into that handle (binary mode for a PDF)
if (ftp_fget($ftp, $handle, 'public/report.pdf', FTP_BINARY)) {
echo "Download complete.\n";
} else {
echo "Download failed.\n";
}
fclose($handle);
ftp_close($ftp);Chiamare ftp_pasv() per abilitare la modalità passiva è quasi sempre necessario quando il client si trova dietro un firewall o NAT, che è il caso più comune; senza di essa il trasferimento dati può bloccarsi.
Scegliere la modalità di trasferimento
FTP_BINARYcopia il file byte per byte. Usala per immagini, archivi, PDF, eseguibili — qualsiasi file che non sia testo normale. È l'impostazione predefinita sicura.FTP_ASCIIconverte i fine riga per adattarli alla piattaforma di destinazione. Usala solo per i file di testo e solo quando vuoi effettivamente tale conversione. Inviare un file binario in modalità ASCII lo corrompe.
Riprendere un download interrotto
Il parametro $offset ti consente di continuare un download che è stato interrotto. Apri il file parziale esistente in modalità append, scopri quanti byte hai già scaricato e indica a ftp_fget() da dove iniziare a scrivere:
<?php
$local = 'downloads/big.iso';
// Open in append mode so previously downloaded bytes are preserved
$handle = fopen($local, 'a');
// How many bytes we already have locally
$alreadyHave = file_exists($local) ? filesize($local) : 0;
if (ftp_fget($ftp, $handle, 'images/big.iso', FTP_BINARY, $alreadyHave)) {
echo "Resumed and finished the download.\n";
}
fclose($handle);Per file molto grandi potresti preferire la variante non bloccante ftp_nb_fget(), che restituisce il controllo al tuo script tra un blocco e l'altro così puoi mostrare l'avanzamento.
Gestione degli errori
ftp_fget() restituisce solo false — non genera eccezioni — quindi verifica il valore di ritorno di ogni passaggio, non solo del download. Il confronto con === evita di interpretare erroneamente un valore falsy ma valido.
<?php
$handle = fopen('downloads/data.csv', 'w');
if ($handle === false) {
exit("Could not open the local file for writing.\n");
}
if (ftp_fget($ftp, $handle, 'exports/data.csv', FTP_ASCII) === false) {
// Common causes: wrong remote path, no read permission, or a dropped data channel
echo "Failed to retrieve the file.\n";
} else {
echo "File retrieved successfully.\n";
}
fclose($handle);Problemi comuni
- Passare un percorso invece di un handle. Il secondo argomento deve essere una risorsa restituita da
fopen(). Se hai un percorso, usa inveceftp_get(). - Dimenticare la modalità passiva. Dietro un firewall, omettere
ftp_pasv()può causare il blocco silenzioso del trasferimento. - Modalità di trasferimento errata. La modalità ASCII danneggia i file binari; la modalità binaria lascia fine riga indesiderati nei file di testo solo su rare piattaforme, quindi il binario è l'impostazione predefinita più sicura.
- Non chiudere le risorse. Chiama
fclose()eftp_close()affinché i buffer vengano svuotati e la connessione venga rilasciata.
Funzioni correlate
ftp_get()— scarica in un percorso locale (nessun handle necessario).ftp_fput()— la controparte per l'upload, che invia dati da un handle aperto.ftp_nb_fget()— download non bloccante in un handle.ftp_connect()eftp_login()— apre e autentica la sessione.