Downloading a file using ftp in php

(PHP 4, PHP 5, PHP 7, PHP 8)

ftp_getDownloads a file from the FTP server

Description

ftp_get(
    FTP\Connection $ftp,
    string $local_filename,
    string $remote_filename,
    int $mode = FTP_BINARY,
    int $offset = 0
): bool

Parameters

ftp

An FTP\Connection instance.

local_filename

The local file path (will be overwritten if the file already exists).

remote_filename

The remote file path.

mode

The transfer mode. Must be either FTP_ASCII or FTP_BINARY.

offset

The position in the remote file to start downloading from.

Return Values

Returns true on success or false on failure.

Changelog

VersionDescription
8.1.0 The ftp parameter expects an FTP\Connection instance now; previously, a resource was expected.
7.3.0 The mode parameter is now optional. Formerly it has been mandatory.

Examples

Example #1 ftp_get() example

<?php// define some variables
$local_file 'local.zip';
$server_file 'server.zip';// set up basic connection
$ftp ftp_connect($ftp_server);// login with username and password
$login_result ftp_login($ftp$ftp_user_name$ftp_user_pass);// try to download $server_file and save to $local_file
if (ftp_get($ftp$local_file$server_fileFTP_BINARY)) {
    echo 
"Successfully written to $local_file\n";
} else {
    echo 
"There was a problem\n";
}
// close the connection
ftp_close($ftp);?>

See Also

  • ftp_pasv() - Turns passive mode on or off
  • ftp_fget() - Downloads a file from the FTP server and saves to an open file
  • ftp_nb_get() - Retrieves a file from the FTP server and writes it to a local file (non-blocking)
  • ftp_nb_fget() - Retrieves a file from the FTP server and writes it to an open file (non-blocking)

CuDi

12 years ago

I tried to ftp a 7mb file today off my webserver.

I copied this example directly and it told me.

Port command successful
"there was a problem"

I thought it was because of the size.
But I guessed it might be cause of my firewall.

So I made the ftp connection passive:

<?PHP...
 
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
 
ftp_pasv($conn_id, true);?>

Ran the script again & it worked fine.

Hope this helps someone

bob at notallhere dot com

9 years ago

Don't want to use an intermediate file?  Use 'php://output' as the filename and then capture the output using output buffering.

ob_start();
$result = ftp_get($ftp, "php://output", $file, FTP_BINARY);
$data = ob_get_contents();
ob_end_clean();

Don't forget to check $result to make sure there wasn't an error.  After that, manipulate the $data variable however you want.

anomie at users dot sf dot net

15 years ago

Why there isn't an "ftp_get_contents" function, I don't know. It takes a little work to emulate one, but it's doable.
<?php
function ftp_get_contents($ftp_stream, $remote_file, $mode, $resume_pos=null){
   
$pipes=stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
    if(
$pipes===false) return false;
    if(!
stream_set_blocking($pipes[1], 0)){
       
fclose($pipes[0]); fclose($pipes[1]);
        return
false;
    }
   
$fail=false;
   
$data='';
    if(
is_null($resume_pos)){
       
$ret=ftp_nb_fget($ftp_stream, $pipes[0], $remote_file, $mode);
    } else {
       
$ret=ftp_nb_fget($ftp_stream, $pipes[0], $remote_file, $mode, $resume_pos);
    }
    while(
$ret==FTP_MOREDATA){
        while(!
$fail && !feof($pipes[1])){
           
$r=fread($pipes[1], 8192);
            if(
$r==='') break;
            if(
$r===false){ $fail=true; break; }
           
$data.=$r;
        }
       
$ret=ftp_nb_continue($ftp_stream);
    }
    while(!
$fail && !feof($pipes[1])){
       
$r=fread($pipes[1], 8192);
        if(
$r==='') break;
        if(
$r===false){ $fail=true; break; }
       
$data.=$r;
    }
   
fclose($pipes[0]); fclose($pipes[1]);
    if(
$fail || $ret!=FTP_FINISHED) return false;
    return
$data;
}
?>

Something similar would work to write a ftp_put_contents function, too.

ramiro at qusarcr dot com

19 years ago

Keep in mind that ftp_get will overwrite the file on your local machine if it has the same name.

Nate from ruggfamily.com

13 years ago

Here's a quick function that figures out the correct mode to use based on a file's extension.

<?php
function get_ftp_mode($file)
{   
   
$path_parts = pathinfo($file);

        if (!isset(

$path_parts['extension'])) return FTP_BINARY;
    switch (
strtolower($path_parts['extension'])) {
        case
'am':case 'asp':case 'bat':case 'c':case 'cfm':case 'cgi':case 'conf':
        case
'cpp':case 'css':case 'dhtml':case 'diz':case 'h':case 'hpp':case 'htm':
        case
'html':case 'in':case 'inc':case 'js':case 'm4':case 'mak':case 'nfs':
        case
'nsi':case 'pas':case 'patch':case 'php':case 'php3':case 'php4':case 'php5':
        case
'phtml':case 'pl':case 'po':case 'py':case 'qmail':case 'sh':case 'shtml':
        case
'sql':case 'tcl':case 'tpl':case 'txt':case 'vbs':case 'xml':case 'xrc':
            return
FTP_ASCII;
    }
    return
FTP_BINARY;
}
// sample usage
ftp_get($conn_id, $local_file, $server_file, get_ftp_mode($server_file));
?>

mroerick at gmx dot net

13 years ago

ftp_sync is a way to walk the directory structure on the server and copy every directory and file to the same location locally.

<?php
$ftp_server
= "ftp.example.com";
$conn_id = ftp_connect ($ftp_server)
    or die(
"Couldn't connect to $ftp_server"); $login_result = ftp_login($conn_id, "user", "pass");
if ((!
$conn_id) || (!$login_result))
    die(
"FTP Connection Failed"); ftp_sync ("DirectoryToCopy");    // Use "." if you are in the current directory ftp_close($conn_id);  // ftp_sync - Copy directory and file structure
function ftp_sync ($dir) {

    global

$conn_id;

    if (

$dir != ".") {
        if (
ftp_chdir($conn_id, $dir) == false) {
            echo (
"Change Dir Failed: $dir<BR>\r\n");
            return;
        }
        if (!(
is_dir($dir)))
           
mkdir($dir);
       
chdir ($dir);
    }
$contents = ftp_nlist($conn_id, ".");
    foreach (
$contents as $file) {

            if (

$file == '.' || $file == '..')
            continue;

                if (@

ftp_chdir($conn_id, $file)) {
           
ftp_chdir ($conn_id, "..");
           
ftp_sync ($file);
        }
        else
           
ftp_get($conn_id, $file, $file, FTP_BINARY);
    }
ftp_chdir ($conn_id, "..");
   
chdir ("..");

}

?>

miki at epoch dot co dot il

9 years ago

If you ran the example and see that it fail after 90sec (timeout).

Then try adding:
<?php
ftp_pasv
($ftp_conn, true);
?>

Aditya P dot Bhatt (adityabhai at gmail dot com)

14 years ago

<?php
               
// define some variables
       
$folder_path = "YOUR FOLDER PATH";
       
$local_file = "LOCAL FILE PATH";
       
$server_file = "SERVER FILE PATH";//-- Connection Settings
       
$ftp_server = "IP ADDRESS"; // Address of FTP server.
       
$ftp_user_name = "USERNAME"; // Username
       
$ftp_user_pass = "PASSWORD"; // Password
        #$destination_file = "FILEPATH";

                // set up basic connection

$conn_id = ftp_connect($ftp_server);// login with username and password
       
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);// try to download $server_file and save to $local_file
       
if (ftp_get($conn_id, $local_file, $server_file, FTP_BINARY)) {
            echo
"Successfully written to $local_file\n";
        } else {
            echo
"There was a problem\n";
        }
// close the connection
       
ftp_close($conn_id);
?>

mpatnode at yahoo dot com

4 years ago

Note that PHP still defaults to FTP active mode by default, which is almost never used anymore since the creation of firewalls.   Don't forget to add a ftp_pasv($conn, true) after your ftp_login.

anomie at users dot sf dot net

15 years ago

Crud. The _nb_ only refers to reading from the ftp server, and the buffer in the socket pair is only about 364 bytes. So it doesn't work for files larger than that size.

administrator at gesoft dot org

16 years ago

Hello everybody,

If someone will try to download files to the same local file (some temporary file), like shown here:

<?php
foreach ($files as $key=>$path) {
...
 
$result = ftp_get($ftpConnId, 'temp.tmp', $path, FTP_BINARY);
...
}
?>

please take in consideration the fact that you will have big problems with downloading (getting) hole files. In other words ‘temp.tmp’ file always will have the same size equal to first downloaded file despite the real size of downloading file. I have not idea what is the reason!

If someone will think that problem is just in getting proper file size (which you will get using filssize() function) he will be mistaken. The download file’s size is not equal to source file’s size materially, that means fflush() function will not solve the problem (I have tried this as well).

Finally the solution was founded: before downloading a file you will need to delete local file if such exist (‘temp.tmp’). So working code will look like:

<?php
foreach ($files as $key=>$path) {
...
  if (
file_exists('temp.tmp')) {
   
unlink('temp.tmp');
  }
 
$result = ftp_get($ftpConnId, 'temp.tmp', $path, FTP_BINARY);
...
}
?>

Good luck in scripting :-)

Vitali Simsive

corey-holzer at nyc dot rr dot com

18 years ago

The zero size file is not a side effect.  When the ftp_get starts the first thing it does is to create the inode/file which it will stream the data too and that is a zero size file with the nname you specified for the local file.  When the download fails it leaves the file in place.

thivierr at telus dot net

18 years ago

If you previously downloaded a file before (like a huge web log), and just want to get the remaining portion, do this:

$local_file_size = filesize($local_file_path);
$get_result = ftp_get($conn_id, $local_file_path, $remote_file_path, FTP_BINARY, $local_file_size);

This same code works regardless of wether the local file exists already or not.  You should first test to make sure the local file is not bigger than the remote file.

Ben Parish

10 years ago

On Windows (and possibly *NIX) you will get "[function.ftp-get]: failed to open stream: No such file or directory in..." errors if the local_file path contains directory paths that do not already exist.

Even with write permissions ftp_get can create the file but it will NOT automatically create the parent directories as you might expect.

apurvavora19 at gmail dot com

4 years ago

I am using ftp_get function to download a file from the FTP server to my web server where my php script is running.
On the webserver, I want the file to be downloaded to a directory which has a structure as follows -> Data/Files/localfilename.exe

However, when I specify the above string in the $local_file_name parameter of ftp_get I get an error saying the file does not exist.

I am running a Windows Server and the php script is running from C:/xampp/htdocs/file.php

Is there any way where I can specify the path on the web server where the file is supposed to be downloaded ?

scott dot chu at udngroup dot com

6 years ago

I'd suggest use ftp_fget() instead of ftp_get() since the latter only return TRUE or FALSE and there's no obvious way to get the cause of failure.

   Using ftp_fget,  you have to pass a file handle as local file, so you have to do fopen() first. By way of this, you can find 'Permission Denied' problem when call fopen(). If you use ftp_get(), there's no way to find this error cause.

   In my case, I run httpd using 'nobody' and I create ftp local folder using 'haha'. It tooks me long time to find the 'Permission Denied' problem at that time since  I use ftp_get() then.

w dot danford at electronics-software dot com

13 years ago

A subtle issue with the ftp_get() function. The second param, string $local_file, is a file name on the SERVER running the php script. It is NOT a file on the client machine running the browser. I erroneously tried to use this ftp to download a file from my site to my local system. I entered the full path starting with the drive letter ("h:/...") on a system running WIN XP and kept getting a failure of unable to open (destination) file. Only after just putting in a file name with no pathing did I see where the file was written. It was in the directory on my site where the php script is located (hosting is managed shared LAMP server which supports multiple url's, GoDaddy hosting).

danny at ingeniarte dot com

11 years ago

Remember to use the full server paths to the directories you are working on. Server paths are not the same as "ftp paths".

I was using the path displayed on my FTP client to download and upload files and I kept getting "Not found" or "Permission Denied" errors.

How to Upload file on ftp server in PHP?

manageable separate text files..
Step 1: Make sure you have permission to connect to/upload to the FTP. server. PHP's FTP functions. ... .
Step 2: Construct an upload form. Next, create a simple HTML form that asks the user for. ... .
Step 3: Create the PHP upload processor. Once the form has been submitted to the Web server, the next..

What is FTP PHP?

PHP FTP Introduction The FTP functions give client access to file servers through the File Transfer Protocol (FTP). The FTP functions are used to open, login and close connections, as well as upload, download, rename, delete, and get information on files from file servers.

How do I get files from an FTP?

How to Copy Files From a Remote System ( ftp ).
Change to a directory on the local system where you want the files from the remote system to be copied. ... .
Establish an ftp connection. ... .
Change to the source directory. ... .
Ensure that you have read permission for the source files. ... .
Set the transfer type to binary..

How can I download file from PHP?

PHP enables you to download file easily using built-in readfile() function. The readfile() function reads a file and writes it to the output buffer..
<? ... .
header('Content-Type: application/octet-stream');.
header("Content-Transfer-Encoding: utf-8");.