杰瑞科技汇

python ftp passive

Of course! Let's break down how to use Python's built-in ftplib module for Passive FTP.

What is Passive FTP (PASV)?

First, a quick refresher. FTP has two modes for transferring data (like files):

  1. Active FTP: The client (Python script) opens a port and tells the server to connect back to it on that port to transfer data. This can be problematic if the client is behind a firewall, as the firewall will block the server's incoming connection.
  2. Passive FTP (PASV): The client asks the server to open a port. The server then tells the client which port it has opened, and the client connects to that server port to transfer data. This is much more firewall-friendly because all connections are initiated from the client's side. This is the modern standard and the one you'll almost always want to use.

The Key Method: ftplib.set_pasv()

To enable Passive mode in Python's ftplib, you simply need to call the set_pasv() method on your FTP instance.

  • ftp.set_pasv(True): Enables Passive mode. This is the default behavior.
  • ftp.set_pasv(False): Disables Passive mode (Active mode).

Since Passive mode is the default, you often don't even need to call it explicitly, but it's excellent practice to do so to make your code's intention clear and to ensure it works correctly on all systems.


Complete Python FTP Example (Passive Mode)

Here is a full, commented example that connects to an FTP server, logs in, lists files, downloads a file, and uploads a file, all in Passive mode.

import ftplib
import os
# --- Configuration ---
# Replace with your FTP server details
FTP_HOST = "ftp.dlptest.com"
FTP_USER = "dlpuser"
FTP_PASS = "rNrKYTX9g7z3RgJR"
# The local file to upload and the remote file to download
LOCAL_FILE_TO_UPLOAD = "my_local_file.txt"
REMOTE_FILE_TO_DOWNLOAD = "README.txt"
def main():
    """
    Main function to demonstrate passive FTP operations.
    """
    # Create a dummy file for uploading
    with open(LOCAL_FILE_TO_UPLOAD, "w") as f:
        f.write("Hello from Python FTP Passive Mode!")
    print(f"Connecting to {FTP_HOST}...")
    # Use a 'with' statement for automatic cleanup (closing the connection)
    try:
        with ftplib.FTP(timeout=30) as ftp:
            # 1. CONNECT and LOGIN
            ftp.connect(FTP_HOST)
            ftp.login(FTP_USER, FTP_PASS)
            print("Login successful.")
            # 2. EXPLICITLY SET PASSIVE MODE (Good Practice)
            # Although it's the default, this makes the intention clear.
            ftp.set_pasv(True)
            print("Passive mode enabled.")
            # 3. LIST FILES
            print("\n--- Listing files in root directory ---")
            ftp.retrlines('LIST')  # LIST command prints the directory listing
            # 4. DOWNLOAD A FILE
            print(f"\n--- Downloading {REMOTE_FILE_TO_DOWNLOAD} ---")
            with open(REMOTE_FILE_TO_DOWNLOAD, "wb") as local_file:
                # The 'retrbinary' command is used for downloading files in binary mode
                ftp.retrbinary(f"RETR {REMOTE_FILE_TO_DOWNLOAD}", local_file.write)
            print(f"Downloaded {REMOTE_FILE_TO_DOWNLOAD} successfully.")
            # 5. UPLOAD A FILE
            print(f"\n--- Uploading {LOCAL_FILE_TO_UPLOAD} ---")
            with open(LOCAL_FILE_TO_UPLOAD, "rb") as local_file:
                # The 'storbinary' command is used for uploading files in binary mode
                ftp.storbinary(f"STOR {LOCAL_FILE_TO_UPLOAD}", local_file)
            print(f"Uploaded {LOCAL_FILE_TO_UPLOAD} successfully.")
            # 6. DELETE THE UPLOADED FILE (optional cleanup)
            print(f"\n--- Deleting {LOCAL_FILE_TO_UPLOAD} from server ---")
            ftp.delete(LOCAL_FILE_TO_UPLOAD)
            print("File deleted from server.")
    except ftplib.all_errors as e:
        print(f"An FTP error occurred: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    finally:
        # Clean up the local dummy file
        if os.path.exists(LOCAL_FILE_TO_UPLOAD):
            os.remove(LOCAL_FILE_TO_UPLOAD)
        if os.path.exists(REMOTE_FILE_TO_DOWNLOAD):
            os.remove(REMOTE_FILE_TO_DOWNLOAD)
        print("\nLocal cleanup complete.")
if __name__ == "__main__":
    main()

Breakdown of the Code

  1. import ftplib: Imports the necessary library.
  2. ftplib.FTP(timeout=30): Creates an FTP object. Setting a timeout is highly recommended to prevent your script from hanging indefinitely if the server is unresponsive.
  3. with ... as ftp:: This is the best way to handle the connection. It ensures that ftp.quit() is called automatically when the block is exited, gracefully closing the connection.
  4. ftp.connect(FTP_HOST): Establishes the connection to the server.
  5. ftp.login(FTP_USER, FTP_PASS): Authenticates with the server.
  6. ftp.set_pasv(True): The key line. It explicitly enables Passive mode. You can comment this line out, and the script will still work the same way because it's the default, but it's good to have it for clarity.
  7. ftp.retrlines('LIST'): Executes the LIST command, which is equivalent to ls on Linux. retrlines is a helper method that processes the line-oriented text response from the server.
  8. ftp.retrbinary(...): Retrieves a file in binary mode.
    • "RETR {filename}": The FTP command to retrieve a file.
    • local_file.write: A function (or a "callback") that ftplib will call for each chunk of data it receives from the server. This is how the file is written to disk.
  9. ftp.storbinary(...): Stores a file in binary mode.
    • "STOR {filename}": The FTP command to store a file on the server.
    • local_file: A file object opened in binary read mode ("rb"). ftplib will read from this object and send its contents to the server.

Common Pitfalls and Troubleshooting

  • Timeout Errors: If the server is slow or the network is unstable, you might get a timeout. Increase the timeout value in ftplib.FTP(timeout=60).
  • "425 Failed to establish connection": This is a classic sign of an Active FTP connection attempt being blocked by a firewall. If you see this, double-check that you have ftp.set_pasv(True) in your code.
  • Permission Errors: Ensure the user you are logging in with has the correct permissions to read from and write to the desired directories on the server.
  • Binary vs. Text Mode: For most files (images, executables, PDFs, etc.), always use retrbinary and storbinary. For plain text files, you could use retrlines (for reading) and storlines (for writing), but binary mode is safer and more universal.
分享:
扫描分享到社交APP
上一篇
下一篇