ftp_put()
The ftp_put() function is a built-in PHP function that uploads a file to an FTP server. In this article, we'll discuss the function in detail and provide you
The PHP ftp_put() function
ftp_put() is a built-in PHP function that uploads a local file to a remote FTP server. It is the upload counterpart of ftp_get(), which downloads a remote file to your machine. This page covers the signature, the all-important transfer modes, a complete working flow, error handling, and the gotchas that trip people up in production.
You reach ftp_put() after you have opened a connection with ftp_connect() and authenticated with ftp_login().
Syntax
ftp_put(
FTP\Connection $ftp,
string $remote_filename,
string $local_filename,
int $mode = FTP_BINARY
): bool| Parameter | Description |
|---|---|
$ftp | The FTP connection handle returned by ftp_connect() or ftp_ssl_connect(). |
$remote_filename | The destination path on the server, e.g. /public_html/index.html. |
$local_filename | The source path on your machine, e.g. ./build/index.html. |
$mode | Transfer mode: FTP_BINARY (default) or FTP_ASCII. Optional since PHP 7.3. |
Returns true on success and false on failure.
Version note: Before PHP 8.1 the first argument was a
resourcereturned byftp_connect(). From PHP 8.1 it is anFTP\Connectionobject. Your code does not change — you still pass whateverftp_connect()returns — butis_resource()checks no longer work on it.
Binary vs. ASCII mode
Choosing the wrong mode is the most common cause of "the upload worked but the file is corrupt":
FTP_BINARYtransfers the bytes exactly as-is. Use it for everything by default — images, archives, PDFs, executables, and even text in practice.FTP_ASCIIrewrites line endings (\n↔\r\n) to match the destination platform. Only meaningful for plain text, and it will silently destroy any binary file. When in doubt, stay onFTP_BINARY.
A complete upload
Always check the return values of each FTP call rather than assuming a step succeeded:
<?php
// 1. Open a connection (false on failure)
$ftp = ftp_connect('ftp.example.com');
if ($ftp === false) {
exit("Could not connect to FTP server.\n");
}
// 2. Authenticate
if (!ftp_login($ftp, 'username', 'password')) {
ftp_close($ftp);
exit("FTP login failed.\n");
}
// 3. Behind a firewall/NAT? Passive mode is almost always required.
ftp_pasv($ftp, true);
// 4. Upload: local file -> remote path, binary mode
$ok = ftp_put($ftp, '/public_html/index.html', './build/index.html', FTP_BINARY);
echo $ok
? "Upload succeeded.\n"
: "Upload failed.\n";
// 5. Always close
ftp_close($ftp);Note the argument order: remote destination first, local source second — the reverse of what many people expect. Mixing these up makes PHP try to read a non-existent local file and the call fails.
Error handling
ftp_put() returns false and emits a PHP warning on failure. Convert that into a clear, actionable result instead of letting a stray warning leak into your output:
<?php
$remote = '/public_html/index.html';
$local = './build/index.html';
// Catch the "no such local file" case before touching the network.
if (!is_readable($local)) {
exit("Local file '$local' is missing or unreadable.\n");
}
if (!ftp_put($ftp, $remote, $local, FTP_BINARY)) {
// Common causes: wrong remote directory, no write permission,
// disk quota exceeded, or passive mode not enabled.
echo "Failed to upload '$local' to '$remote'.\n";
} else {
echo "Uploaded '$local' to '$remote'.\n";
}
ftp_close($ftp);Common failure causes
- Wrong argument order — remote path and local path swapped.
- Passive mode not set — most servers behind NAT need
ftp_pasv($ftp, true)after login. - Missing remote directory —
ftp_put()does not create folders; useftp_mkdir()first. - No write permission or quota exceeded on the server side.
- Wrong transfer mode corrupting a binary file (use
FTP_BINARY).
Uploading from an open stream
If your data is already an open file handle (or comes from a stream wrapper rather than a path on disk), use ftp_fput() instead — it takes a stream resource in place of a local filename.
Conclusion
ftp_put() uploads a local file to a remote FTP server. Remember the three things that cause most problems: pass the remote path first, keep FTP_BINARY unless you have a specific reason for ASCII, and check every return value. For non-blocking transfers that don't stall your script, see ftp_nb_put().