ftp_fget()
A função ftp_fget() do PHP baixa um arquivo remoto do servidor FTP e o salva em um identificador de arquivo local aberto.
O que é ftp_fget()?
ftp_fget() faz o download de um arquivo de um servidor FTP e o grava em um identificador de arquivo local já aberto. Essa é a principal diferença em relação a ftp_get(): ftp_get() recebe um caminho local e cria o arquivo para você, enquanto ftp_fget() recebe um recurso de arquivo aberto (o valor retornado por fopen()). Como você controla o identificador, ftp_fget() é útil quando você quer gravar em um stream que não é um arquivo comum — um stream temporário (php://temp), um buffer em memória ou um identificador que você posicionou com fseek().
Esta página aborda a assinatura da função, um download completo e funcional, como escolher um modo de transferência, como retomar um download interrompido e o tratamento de erros necessário em código real.
A extensão FTP procedural ainda faz parte do PHP. A partir do PHP 8.1, a conexão é um objeto
FTP\Connectionem vez de umresource, mas o código que você escreve permanece o mesmo. Para transferências criptografadas, useftp_ssl_connect()no lugar deftp_connect().
Sintaxe de ftp_fget()
ftp_fget(
FTP\Connection $ftp,
resource $stream,
string $remote_filename,
int $mode = FTP_BINARY,
int $offset = 0
): bool| Parâmetro | Descrição |
|---|---|
$ftp | A conexão retornada por ftp_connect() (e autenticada com ftp_login()). |
$stream | Um ponteiro de arquivo local aberto no qual os dados baixados serão gravados. Deve ser aberto para escrita ('w', 'w+', 'a', etc.). |
$remote_filename | Caminho para o arquivo no servidor FTP. |
$mode | Modo de transferência: FTP_BINARY (o padrão desde o PHP 7.3) para qualquer arquivo não textual, ou FTP_ASCII para texto simples cujas terminações de linha devem ser normalizadas. |
$offset | Posição em bytes no stream local a partir da qual começar a gravar — usado para retomar um download parcial. O padrão é 0. |
Retorna true em caso de sucesso e false em caso de falha.
Fazendo download de um arquivo com ftp_fget()
Um download completo tem quatro etapas: conectar, fazer login, abrir um identificador local e depois buscar. Sempre feche tanto o identificador quanto a conexão quando terminar.
<?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);Chamar ftp_pasv() para habilitar o modo passivo é quase sempre necessário quando o cliente está atrás de um firewall ou NAT, que é o caso mais comum; sem isso, a transferência de dados pode travar.
Escolhendo um modo de transferência
FTP_BINARYcopia o arquivo byte a byte. Use-o para imagens, arquivos compactados, PDFs, executáveis — qualquer coisa que não seja texto simples. É o padrão seguro.FTP_ASCIIconverte as terminações de linha para corresponder à plataforma de destino. Use-o apenas para arquivos de texto e somente quando você realmente deseja essa conversão. Enviar um arquivo binário no modo ASCII o corrompe.
Retomando um download interrompido
O parâmetro $offset permite continuar um download que foi interrompido. Abra o arquivo parcial existente para acrescentar dados, descubra quantos bytes você já tem e informe a ftp_fget() para começar a gravar a partir daí:
<?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);Para arquivos muito grandes, você pode preferir a variante não bloqueante ftp_nb_fget(), que devolve o controle ao seu script entre os blocos para que você possa exibir o progresso.
Tratamento de erros
ftp_fget() retorna apenas false — não lança exceções — portanto verifique o valor de retorno de cada etapa, não apenas o do download. Comparar com === evita tratar um valor falso, mas válido, de forma incorreta.
<?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);Armadilhas comuns
- Passar um caminho em vez de um identificador. O segundo argumento deve ser um recurso proveniente de
fopen(). Se você tiver um caminho, useftp_get(). - Esquecer o modo passivo. Atrás de um firewall, pular
ftp_pasv()pode fazer a transferência travar silenciosamente. - Modo de transferência errado. O modo ASCII danifica arquivos binários; o modo binário deixa terminações de linha inconsistentes em arquivos de texto apenas em plataformas raras, portanto o binário é o padrão mais seguro.
- Não fechar os recursos. Chame
fclose()eftp_close()para que os buffers sejam liberados e a conexão seja encerrada.
Funções relacionadas
ftp_get()— faz download para um caminho local (sem necessidade de identificador).ftp_fput()— o equivalente de upload, enviando a partir de um identificador aberto.ftp_nb_fget()— download não bloqueante em um identificador.ftp_connect()eftp_login()— abrem e autenticam a sessão.