W3docs

ftp_fget()

The ftp_fget() function is a PHP built-in function that retrieves a remote file from the FTP server and saves it to a local file. The function takes three

What is ftp_fget()?

ftp_fget() downloads a file from an FTP server and writes it into an already-open local file handle. This is the key difference from ftp_get(): ftp_get() takes a local path and creates the file for you, while ftp_fget() takes an open file resource (the value returned by fopen()). Because you control the handle, ftp_fget() is handy when you want to write to a stream that is not a plain file — a temporary stream (php://temp), an in-memory buffer, or a handle you have positioned with fseek().

This page covers the function's signature, a complete working download, how to choose a transfer mode, how to resume an interrupted download, and the error handling you need in real code.

The procedural FTP extension is still part of PHP. As of PHP 8.1 the connection is an FTP\Connection object rather than a resource, but the code you write is unchanged. For encrypted transfers use ftp_ssl_connect() in place of ftp_connect().

Syntax of ftp_fget()

ftp_fget(
    FTP\Connection $ftp,
    resource $stream,
    string $remote_filename,
    int $mode = FTP_BINARY,
    int $offset = 0
): bool
ParameterDescription
$ftpThe connection returned by ftp_connect() (and authenticated with ftp_login()).
$streamAn open local file pointer that the downloaded data is written into. It must be opened for writing ('w', 'w+', 'a', etc.).
$remote_filenamePath to the file on the FTP server.
$modeTransfer mode: FTP_BINARY (the default since PHP 7.3) for any non-text file, or FTP_ASCII for plain text that should have its line endings normalized.
$offsetByte position in the local stream from which to start writing — used to resume a partial download. Defaults to 0.

It returns true on success and false on failure.

Downloading a file with ftp_fget()

A complete download has four steps: connect, log in, open a local handle, then fetch. Always close both the handle and the connection when you are done.

<?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);

Calling ftp_pasv() to enable passive mode is almost always required when the client sits behind a firewall or NAT, which is the common case; without it the data transfer can hang.

Choosing a transfer mode

  • FTP_BINARY copies the file byte-for-byte. Use it for images, archives, PDFs, executables — anything that is not plain text. It is the safe default.
  • FTP_ASCII converts line endings to match the destination platform. Only use it for text files, and only when you actually want that conversion. Sending a binary file in ASCII mode corrupts it.

Resuming an interrupted download

The $offset parameter lets you continue a download that was cut off. Open the existing partial file for appending, find out how many bytes you already have, and tell ftp_fget() to start writing from there:

<?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);

For very large files you may prefer the non-blocking variant ftp_nb_fget(), which returns control to your script between chunks so you can show progress.

Error handling

ftp_fget() only returns false — it does not throw — so check the return value of every step, not just the download. Comparing with === avoids treating a falsy-but-valid value incorrectly.

<?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);

Common pitfalls

  • Passing a path instead of a handle. The second argument must be a resource from fopen(). If you have a path, use ftp_get() instead.
  • Forgetting passive mode. Behind a firewall, skip ftp_pasv() and the transfer may silently hang.
  • Wrong transfer mode. ASCII mode mangles binary files; binary mode leaves stray line endings in text files only on rare platforms, so binary is the safer default.
  • Not closing resources. Call fclose() and ftp_close() so buffers flush and the connection is released.

Practice

Practice
What is the functionality of the ftp_fget() function in PHP?
What is the functionality of the ftp_fget() function in PHP?
Was this page helpful?