- Создал(а) Aleksandr Savkin, редактировал(а) Vasily Selivantsev янв. 26, 2023
resources/send_message_and_files/ftp.py
This module provides a high-level interface for sending files to the FTP server in a form of FTPClient class.
When initializing an instance of the class (if parameter check_connection = True), it tries to connect to the ftp server and will cause an error if the connection failed.
If at the start of the script this check was successful - no errors will be caused - the script will automatically try to reconnect.
The class keeps only one connection active at the same time. The connection is closed after the transfer.
All files that are sent by the FTPClient.send method are added to the queue. Then, in a separate thread, the worker of sending files from the queue starts.
The logic is something like this:
- We take the first file from the queue;
- Trying to send it;
- If the ftplib.all_errors error occurred while sending, the file is returned to the end of the queue and status.ftp_error is passed to the callback ;
- If another error is occurred, the file is not returned to the queue, and status.error is returned to the callback ;
- If the file has been successfully sent, status.success is passed to the callback ;
- Back to the first point (taking the next file).
Class attributes
host (str)
: FTP server address.port (int, optional)
: FTP server port, 21 by default.user (str, optional)
: FTP user name. anonymous by default.passwd (str, optional)
: FTP user password. Empty string by default.work_dir (str, optional)
: Folder on the ftp server where all files will be sent. If not specified, all files are sent to the ftp root directory.callback (callable[str, str])
: Callback function where the guid and task status are passed.queue_maxlen (int, optional)
: The maximum length of the transfer queue. 1000 by default.check_connection (bool, optional)
: If True - checks the connection at initialization. Raises CheckConnectionError if no connection is available. True by default.
Class methods
check_connection()
- Checks the connection to the server. Raises CheckConnectionError if no connection is available.send(file_path, remote_dir=None, callback=None, task_guid=None)
- Sets up a task for sending to the ftp server. Returns the task guid.
Method arguments:file_path (str)
: Full path to the file to be uploaded.remote_dir (str, optional)
: The folder on the remote server where you need to save the file. If the work_dir parameter is set, then it is also taken into account when sending a file.callback (callable[str, str])
: Callback function, where the guid and task status are passed. If not set, the function passed to the callback parameter of the class is used.task_guid (str)
: Task guid. By default, it is set using the function host.random_guid() .
File upload statuses
Possible file upload statuses are contained in the status object:
status.sending
- File is being sent.status.error
- File sending error.status.ftp_error
- FTP connection error.- status.success - File has been sent successfully.
status.in_queue
- The file has been added to the send queue.
Code examples
Tracking the file upload status
When initializing the class, you can specify the callback function that will be called during the file transfer process.
The function takes two arguments:
task_guid (str)
- Task guid (also returned when calling the transfer function).state (str)
- Current status of the file transfer.
import os import host from ftp import FTPClient, status tasks = {} def callback(task_guid, state): popup = host.error if state == status.success or state == status.in_queue: popup = host.message elif state == status.sending: popup = host.alert popup("%s: %s" % (task_guid, state)) if state == status.success: os.remove(tasks[task_guid]) client = FTPClient("localhost", port=21, user="trassir", passwd="12345", callback=callback) file_to_send = "../file1.txt" task_guid = client.send("../file1.txt") tasks[task_guid] = file_to_send
Sending files to different directories
If you need to send files to different directories - DO NOT CREATE DIFFERENT CLASS INSTANCES. The global directory in which the script will run can be set for the class. A separate directory for each file can be set as well. Global one is set during the class initialization - using the work_dir argument. When sending a file, the FTPClient.send method can take an optional remote_dir argument.
Sending files to FTP root
ftp
│ file1.txt
│ file2.txt
from ftp import FTPClient client = FTPClient("localhost", port=21, user="trassir", passwd="12345") client.send("../file1.txt") client.send("../file2.txt")
Sending all files to mypath directory
ftp
└───mypath
│ file1.txt
│ file2.txt
from ftp import FTPClient client = FTPClient("localhost", port=21, user="trassir", passwd="12345", work_dir="mypath") client.send("../file1.txt") client.send("../file2.txt")
Sending each file to a different directory
ftp
└───file1_dir
│ │ file1.txt
│
└───file2_dir
└───subdir
│ file2.txt
from ftp import FTPClient client = FTPClient("localhost", port=21, user="trassir", passwd="12345") client.send("../file1.txt", remote_dir="file1_dir") client.send("../file2.txt", remote_dir="file2_dir/subdir")
Complex directory hierarchy
We will use the script_path folder on the FTP server and at the same time, inside this folder, we will create different folders for each file.
ftp
└───script_path
└───file1_dir
| │ file1.txt
└───file2_dir
└───subdir
| file2.txt
from ftp import FTPClient client = FTPClient("localhost", port=21, user="trassir", passwd="12345", work_dir="script_path") client.send("../file1.txt", remote_dir="file1_dir") client.send("../file2.txt", remote_dir="file2_dir/subdir")
- Нет меток