使用pyftpdlib/ftplib时,如何检测并移除FTP中断传输的部分文件?
解决FTP传输中断时服务器自动清理部分文件的方案
针对用pyftpdlib搭建的FTP服务器,以下几种方案可以确保连接断开时自动识别并移除未完成的部分文件:
1. 利用pyftpdlib内置的传输中断钩子
pyftpdlib的FTPHandler提供了on_file_incomplete回调,专门在文件接收中断时触发。你可以自定义处理器类重写这个方法,直接删除临时文件:
from pyftpdlib.handlers import FTPHandler import os class CleanupFTPHandler(FTPHandler): def on_file_incomplete(self, file_path): # file_path是接收中断时的临时文件路径 if os.path.exists(file_path): os.remove(file_path) print(f"已清理中断传输的部分文件: {file_path}")
默认情况下,pyftpdlib会用临时文件名接收文件(比如接收过程中使用filename.tmp,完成后重命名为目标文件名),传输中断时临时文件会保留,on_file_incomplete会自动触发并执行清理逻辑。
2. 结合连接断开事件跟踪传输状态
如果需要更精细的控制,可以跟踪当前正在传输的文件,在连接断开时批量清理未完成的文件:
from pyftpdlib.handlers import FTPHandler import os class CleanupFTPHandler(FTPHandler): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.active_transfers = set() # 记录当前正在上传的文件路径 def pre_process_command(self, cmd, arg): # 捕获STOR命令(客户端发起上传),记录目标文件 if cmd.upper() == "STOR": target_file = os.path.join(self.fs.getcwd(), arg) self.active_transfers.add(target_file) return super().pre_process_command(cmd, arg) def on_file_received(self, file_path): # 文件接收完成,从跟踪集合中移除 if file_path in self.active_transfers: self.active_transfers.remove(file_path) def on_disconnect(self): # 连接断开时,清理所有未完成的临时文件 for target_file in self.active_transfers: # 假设临时文件为目标文件名加.part后缀 temp_file = f"{target_file}.part" if os.path.exists(temp_file): os.remove(temp_file) print(f"连接断开,清理未完成文件: {temp_file}") super().on_disconnect()
这种方式需要你在接收文件时主动使用临时后缀(比如.part),上传完成后再重命名为正式文件名,确保未完成的文件能被准确识别。
3. 可选:文件大小校验兜底
如果担心回调没触发,可以定期扫描服务器目录,对比文件实际大小和客户端预先声明的大小(需要客户端配合)。比如客户端上传前通过SIZE命令告知文件大小,服务器接收后校验,若大小不符则判定为未完成文件并删除。
注意事项
- 确保pyftpdlib使用最新版本,旧版本的钩子函数行为可能存在差异。
- 服务器进程需要具备对应目录的文件删除权限,避免清理失败。
- 被动模式(PASV)下,确保连接断开事件能被正确捕获(pyftpdlib默认会处理)。
内容的提问来源于stack exchange,提问作者Satya Bharadwaj
相关产品推荐
相关产品推荐

