Signals
Django FTP Server provides Django signals that are emitted when various FTP events occur. This allows you to hook into FTP server events for logging, auditing, or custom processing.
Available Signals
All signals are defined in django_ftpserver.signals.
Connection Signals
ftp_server_startedSent when the FTP server starts.
- Arguments:
sender: The command classserver: The FTPServer instancehost: Server host addressport: Server port number
ftp_server_stoppedSent when the FTP server stops.
- Arguments:
sender: The command classserver: The FTPServer instancehost: Server host addressport: Server port number
ftp_client_connectedSent when a client connects to the server.
- Arguments:
sender: The handler classhandler: The FTPHandler instanceremote_ip: Client IP addressremote_port: Client port number
ftp_client_disconnectedSent when a client disconnects from the server.
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Username (if authenticated, otherwise None)remote_ip: Client IP address
Authentication Signals
ftp_loginSent when a user successfully logs in.
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernameremote_ip: Client IP address
ftp_login_failedSent when a login attempt fails.
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Attempted usernameremote_ip: Client IP address
ftp_logoutSent when a user logs out.
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernameremote_ip: Client IP address
File Transfer Signals
ftp_file_receivedSent when a file upload completes successfully.
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernamepath: File pathremote_ip: Client IP address
ftp_file_sentSent when a file download completes successfully.
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernamepath: File pathremote_ip: Client IP address
ftp_file_received_incompleteSent when a file upload is interrupted.
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernamepath: File pathremote_ip: Client IP address
ftp_file_sent_incompleteSent when a file download is interrupted.
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernamepath: File pathremote_ip: Client IP address
File Operation Signals
ftp_file_deletedSent when a file is deleted (DELE command).
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernamepath: Deleted file pathremote_ip: Client IP address
ftp_file_renamedSent when a file or directory is renamed (RNFR/RNTO commands).
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernamepath_from: Original pathpath_to: New pathremote_ip: Client IP address
ftp_directory_createdSent when a directory is created (MKD command).
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernamepath: Created directory pathremote_ip: Client IP address
ftp_directory_deletedSent when a directory is deleted (RMD command).
- Arguments:
sender: The handler classhandler: The FTPHandler instanceusername: Usernamepath: Deleted directory pathremote_ip: Client IP address
Usage Examples
Basic Signal Receiver
Create a file receivers.py in your Django app:
import logging
from django.dispatch import receiver
from django_ftpserver.signals import ftp_login, ftp_logout, ftp_login_failed
logger = logging.getLogger('ftp.access')
@receiver(ftp_login)
def log_ftp_login(sender, username, remote_ip, **kwargs):
logger.info("FTP login: user=%s, ip=%s", username, remote_ip)
@receiver(ftp_logout)
def log_ftp_logout(sender, username, remote_ip, **kwargs):
logger.info("FTP logout: user=%s, ip=%s", username, remote_ip)
@receiver(ftp_login_failed)
def log_ftp_login_failed(sender, username, remote_ip, **kwargs):
logger.warning("FTP login failed: user=%s, ip=%s", username, remote_ip)
Make sure to import your receivers in your app’s apps.py:
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'myapp'
def ready(self):
import myapp.receivers # noqa
File Upload Processing
Process uploaded files (e.g., virus scanning, thumbnail generation):
from django.dispatch import receiver
from django_ftpserver.signals import ftp_file_received
@receiver(ftp_file_received)
def process_uploaded_file(sender, username, path, **kwargs):
# Queue async task for heavy processing
from myapp.tasks import process_file
process_file.delay(path, username)
Audit Logging
Store FTP events in a database for auditing:
from django.dispatch import receiver
from django_ftpserver.signals import (
ftp_login, ftp_logout,
ftp_file_received, ftp_file_sent, ftp_file_deleted
)
from myapp.models import FTPAuditLog
@receiver(ftp_login)
def audit_login(sender, username, remote_ip, **kwargs):
FTPAuditLog.objects.create(
event_type='login',
username=username,
remote_ip=remote_ip,
)
@receiver(ftp_file_received)
def audit_upload(sender, username, path, remote_ip, **kwargs):
FTPAuditLog.objects.create(
event_type='upload',
username=username,
remote_ip=remote_ip,
path=path,
)
@receiver(ftp_file_deleted)
def audit_delete(sender, username, path, remote_ip, **kwargs):
FTPAuditLog.objects.create(
event_type='delete',
username=username,
remote_ip=remote_ip,
path=path,
)
Debug Logging
The FTP handlers emit DEBUG level logs for all events. You can enable these logs in your Django settings:
LOGGING = {
'version': 1,
'handlers': {
'console': {'class': 'logging.StreamHandler'},
},
'loggers': {
'django_ftpserver.handlers': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
To disable the debug logs, set the level to INFO or higher:
LOGGING = {
'version': 1,
'loggers': {
'django_ftpserver.handlers': {
'level': 'INFO',
},
},
}
Handler Classes
To use signals, make sure you are using the Django FTP handlers. By default, the management command uses these handlers automatically.
Available handlers:
django_ftpserver.handlers.DjangoFTPHandler- FTP handler with signal supportdjango_ftpserver.handlers.DjangoTLS_FTPHandler- TLS FTP handler with signal support (requires pyOpenSSL)
You can also specify custom handlers in your Django settings:
FTPSERVER_HANDLER = 'django_ftpserver.handlers.DjangoFTPHandler'
FTPSERVER_TLSHANDLER = 'django_ftpserver.handlers.DjangoTLS_FTPHandler'