PHP ftp_nb_put() Function

PHP

PHP ftp_nb_put() - Non-blocking FTP Upload

The ftp_nb_put() function in PHP enables uploading files to an FTP server asynchronously, allowing your script to perform other tasks without waiting for the file transfer to complete. This non-blocking upload method is particularly useful when handling large files or when you want to maintain responsiveness in your applications during FTP operations.

Introduction

Uploading files to an FTP server is a common task in web development and system administration. The traditional ftp_put() function blocks PHP execution until the upload finishes, which can lead to slow performance or timeouts when transferring large files. PHP's ftp_nb_put() (non-blocking put) function addresses this by allowing uploads to happen in the background while PHP continues execution.

In this tutorial, you will learn how to use ftp_nb_put() to perform asynchronous FTP uploads and how to manage checks for upload progress using this function.

Prerequisites

  • PHP installed on your server (PHP 4.3.0 or higher, as ftp_nb_put() requires PHP 4.3.0+)
  • Enable PHP FTP extension (usually enabled by default, but verify with phpinfo();)
  • Access credentials (hostname, username, password) for an FTP server
  • Basic knowledge of FTP and PHP scripting

Setup Steps

  1. Make sure the FTP extension is enabled in your PHP configuration.
  2. Establish an FTP connection using ftp_connect().
  3. Log in to the FTP server with ftp_login().
  4. Use ftp_nb_put() to start uploading the file asynchronously.
  5. Use a loop with ftp_nb_continue() to keep the upload progressing.
  6. Once the upload completes, close the FTP connection.

Understanding ftp_nb_put() Function

The function signature is:

int ftp_nb_put(
    resource $ftp_stream,
    string $remote_file,
    string $local_file,
    int $mode = FTP_BINARY,
    int $startpos = 0
)

Parameters:

  • $ftp_stream - FTP connection resource.
  • $remote_file - Path where the file will be saved on the FTP server.
  • $local_file - Path of the local file to upload.
  • $mode - Transfer mode: FTP_BINARY (default) or FTP_ASCII.
  • $startpos - Optional; specify the position to start uploading from (useful for resumable uploads).

Returns:

  • FTP_MOREDATA if upload is in progress.
  • FTP_FINISHED if upload finished successfully.
  • FALSE if there is an error.

Example: Asynchronous File Upload with ftp_nb_put()

The following example uploads a local file to an FTP server asynchronously:

<?php
// FTP server credentials
$ftp_server = "ftp.example.com";
$ftp_user = "username";
$ftp_pass = "password";

// Connect to FTP server
$conn_id = ftp_connect($ftp_server);
if (!$conn_id) {
    die("Could not connect to FTP server");
}

// Log in to FTP
if (!ftp_login($conn_id, $ftp_user, $ftp_pass)) {
    ftp_close($conn_id);
    die("FTP login failed");
}

ftp_pasv($conn_id, true); // Enable passive mode

$local_file = "/path/to/local/file.zip";
$remote_file = "uploads/file.zip";

// Start non-blocking upload
$ret = ftp_nb_put($conn_id, $remote_file, $local_file, FTP_BINARY);

while ($ret == FTP_MOREDATA) {
    // Do other tasks or sleep to avoid CPU overload
    echo "Uploading in progress...\n";
    // Continue upload
    $ret = ftp_nb_continue($conn_id);
}

if ($ret == FTP_FINISHED) {
    echo "Upload finished successfully!\n";
} else {
    echo "Error during upload\n";
}

// Close connection
ftp_close($conn_id);
?>

Explanation:

  • Connect and authenticate to the FTP server.
  • Set passive mode with ftp_pasv() (recommended for firewall traversal).
  • Call ftp_nb_put() to initiate the upload.
  • While the upload returns FTP_MOREDATA, keep calling ftp_nb_continue() to upload the next portion.
  • Once it returns FTP_FINISHED, the upload is complete.
  • If FALSE is returned, handle the error appropriately.

Best Practices

  • Enable Passive Mode: Use ftp_pasv() to enable passive mode for better firewall compatibility.
  • Handle Upload Progress: Consider updating users or logging progress inside the while loop where ftp_nb_continue() is called.
  • Chunked Uploads: For very large files, you can implement resume logic using the $startpos parameter to restart uploads after interruptions.
  • Use Binary Mode for Binary Files: Always use FTP_BINARY when uploading binary files (images, videos, archives) to avoid corruption.
  • Set Timeouts and Error Handling: Properly handle errors and consider scripting timeouts while waiting for upload progress to prevent hanging scripts.

Common Mistakes

  • Not using ftp_nb_continue() inside a loop to continue the upload after ftp_nb_put().
  • Confusing ftp_put() (blocking) and ftp_nb_put() (non-blocking), leading to incorrect handling of return values.
  • Not enabling passive mode, which can cause uploads to fail behind strict firewalls.
  • Wrong transfer mode selection causing file corruption (e.g., using FTP_ASCII for binary files).
  • Failing to check for errors returned during connection, login, or upload stages.

Interview Questions

Junior Level

  • Q1: What is the main difference between ftp_put() and ftp_nb_put()?
    A1: ftp_put() blocks script execution until upload finishes, while ftp_nb_put() uploads file asynchronously without blocking.
  • Q2: What does ftp_nb_put() return when the upload is still in progress?
    A2: It returns FTP_MOREDATA to indicate the upload isn’t finished yet.
  • Q3: Which function should you call repeatedly to continue an upload started with ftp_nb_put()?
    A3: You should call ftp_nb_continue() until it returns FTP_FINISHED.
  • Q4: How do you start an FTP connection in PHP?
    A4: Use ftp_connect() with the FTP server’s hostname.
  • Q5: Why should you enable passive mode using ftp_pasv() before uploading?
    A5: Passive mode helps to avoid firewall issues during FTP data transfer.

Mid Level

  • Q1: What arguments are required to use ftp_nb_put() effectively?
    A1: You need a valid FTP stream, remote filename, local filename, optional mode (FTP_BINARY or FTP_ASCII), and optional start position.
  • Q2: How can you handle large files with non-blocking FTP uploads?
    A2: Use ftp_nb_put() in a loop with ftp_nb_continue(), optionally using the $startpos parameter to resume interrupted uploads.
  • Q3: What is a practical scenario for using ftp_nb_put() over ftp_put()?
    A3: When uploading large files asynchronously to avoid PHP script blocking or timeouts on slow connections.
  • Q4: How should errors during asynchronous upload be handled?
    A4: Check the return value of ftp_nb_put() and ftp_nb_continue() for FALSE and implement retry or error-logging logic.
  • Q5: What transfer modes are available for ftp_nb_put() and which one is typically preferred?
    A5: FTP_ASCII and FTP_BINARY; FTP_BINARY is preferred for binary files to prevent corruption.

Senior Level

  • Q1: How does non-blocking FTP upload improve performance in PHP applications?
    A1: It allows the script to perform other operations or user interactions during file upload, reducing wait time and improving responsiveness.
  • Q2: Explain how to implement resume support in uploading files using ftp_nb_put().
    A2: Use the $startpos parameter to specify the byte offset to resume an interrupted upload, and verify remote file size before resuming.
  • Q3: What are the potential drawbacks or limitations of using ftp_nb_put()?
    A3: It requires explicit looping and error handling, can complicate scripts, and its non-blocking nature might increase resource usage if not carefully managed.
  • Q4: How would you integrate ftp_nb_put() with event-driven or asynchronous PHP codebases?
    A4: By using event loops or asynchronous frameworks (like ReactPHP), you can poll ftp_nb_continue() without blocking and integrate uploads with other async operations.
  • Q5: Can you combine ftp_nb_put() with parallel uploads? If yes, how?
    A5: Yes, by opening multiple FTP connections and using ftp_nb_put() on each in separate loops or asynchronous contexts to upload files simultaneously.

FAQ

Q: What is the difference between ftp_nb_put() and ftp_put()?

A: ftp_put() blocks the PHP script until the upload finishes, while ftp_nb_put() initiates a non-blocking upload allowing you to continue running code while the file is uploading.

Q: How do I check if the upload via ftp_nb_put() is complete?

A: Use ftp_nb_continue() repeatedly until it returns FTP_FINISHED, indicating upload completion.

Q: Can I use ftp_nb_put() to resume interrupted uploads?

A: Yes, by specifying the $startpos parameter to continue uploading from a byte offset.

Q: Is it necessary to use passive mode with ftp_nb_put()?

A: While not obligatory, enabling passive mode (ftp_pasv()) is highly recommended to avoid firewall or NAT issues.

Q: What transfer mode should I use with binary files?

A: Always use FTP_BINARY mode to prevent data corruption during transfer.

Conclusion

The PHP ftp_nb_put() function is a powerful tool for uploading files asynchronously to FTP servers, enhancing your application’s performance and user experience—especially with large files. By managing the upload in a non-blocking manner, you keep your PHP scripts responsive and flexible. Follow the outlined best practices and avoid common pitfalls to effectively incorporate non-blocking FTP uploads into your projects.