领导需求:基于Python开发一个小工具,使其能够实现从目标FTP服务器指定路径中实时轮训下载或更新文件到本地指定路径,仅供学习或参考。
SQLite3安装教程:点击转到我参考的SQLite安装教程
废话不多说直接上代码:
FTPwindow.py:
# -*- coding: utf-8 -*-
import time
import os
from ftplib import FTP, error_perm
import configparser
import datetime
from datetime import datetime
import sqlite
class FTP_OP:
def __init__(self, host, username, password, port, passive):
self.host = host
self.username = username
self.password = password
self.port = port
self.passive = passive
self.downloaded_files = {}
def ftp_connect(self):
try:
ftp = FTP()
ftp.encoding = 'gbk'
ftp.set_debuglevel(0)
ftp.connect(self.host, self.port)
ftp.login(self.username, self.password)
ftp.set_pasv(self.passive)
return ftp
except Exception as e:
print(f"连接ftp server失败:{e}")
return None
def download_directory(self, ftp, path, local_path):
try:
file_list = []
ftp.retrlines('LIST', file_list.append)
for file in file_list:
split = file.split()
permissions = split[0]
file_name = split[-1]
file_size = split[4] # 获取文件大小
file_mtime = split[5] + ' ' + split[6] # 获取文件修改时间
if permissions.startswith('d'):
new_path = os.path.join(path, file_name)
local_new_path = os.path.join(local_path, file_name)
print("正在创建对应目录:", new_path)
os.makedirs(local_new_path, exist_ok=True)
ftp.cwd(file_name)
self.download_directory(ftp, new_path, local_new_path)
ftp.cwd('..')
else:
file_path = os.path.join(local_path, file_name)
if file_name not in self.downloaded_files:
last_size, last_mtime = None, None
else:
# 获取字典中保存的文件大小和修改时间
last_size, last_mtime = self.downloaded_files[file_name]
if file_name in self.downloaded_files:
# 比较FTP服务器中的文件大小和修改时间与字典中的是否一致
if file_size == last_size and self.compare_time(file_mtime, last_mtime):
print(f"文件 '{file_name}' 未做过任何变化,无需更新")
continue
print(f"正在下载文件:{file_path}")
with open(file_path, 'wb') as f:
ftp.retrbinary(f'RETR {file_name}', f.write)
# 将文件名、文件大小和修改时间保存到字典中
self.downloaded_files[file_name] = (file_size, file_mtime)
if file_size != last_size:
print(f"文件 '{file_name}' 根据大小判断有变化,进行了更新")
updatetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
sqlite.insert(file_name, file_size, updatetime,file_mtime)
else:
print(f"文件 '{file_name}' 根据修改时间判断有变化,进行了更新")
updatetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
sqlite.insert(file_name, file_size,updatetime, file_mtime)
except Exception as e:
print(f"下载目录失败:{e}")
def compare_time(self, time1, time2):
# 将时间字符串转换为datetime对象
dt1 = datetime.strptime(time1, '%b %d')
dt2 = datetime.strptime(time2, '%b %d')
return dt1 == dt2
def download_file(self, ftp_filefolder, dst_filefolder):
try:
ftp = self.ftp_connect()
if ftp is not None:
ftp.cwd(ftp_filefolder)
self.download_directory(ftp, ftp_filefolder, dst_filefolder)
ftp.quit()
except Exception as e:
print(f"下载文件失败:{e}")
def read_config(config_file):
config = configparser.ConfigParser()
config.read(config_file)
host = config.get('FTP', 'host')
username = config.get('FTP', 'username')
password = config.get('FTP', 'password')
port = config.getint('FTP', 'port')
ftp_filefolder = config.get('FTP', 'ftp_filefolder')
dst_filefolder = config.get('FTP', 'dst_filefolder')
return host, username, password, port, ftp_filefolder, dst_filefolder
if __name__ == '__main__':
config_file = 'config.ini'
host, username, password, port, ftp_filefolder, dst_filefolder = read_config(config_file)
os.makedirs(dst_filefolder, exist_ok=True)
sqlite = sqlite.Sqlite() # 创建 Sqlite 实例
ftp = FTP_OP(host, username, password, port, passive=False)
try:
while True:
ftp.download_file(ftp_filefolder, dst_filefolder)
time.sleep(10)
except KeyboardInterrupt:
print('用户终止程序')
sqlite.py:
import sqlite3
class Sqlite:
def __init__(self):
self.conn = sqlite3.connect('ftpdown_log.db')
print("Opened database successfully")
self.cursor = self.conn.cursor()
self.create_table()
self.select()
def create_table(self):
create_table = '''CREATE TABLE IF NOT EXISTS ftpdown_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
file_name TEXT ,
file_size TEXT ,
update_time TEXT ,
file_mtime TEXT
);
'''
self.cursor.execute(create_table)
self.conn.commit()
print("Table created successfully")
def insert(self, file_name, file_size, update_time, file_mtime):
insert_data = f"INSERT INTO ftpdown_log (file_name, file_size, update_time,file_mtime) VALUES (?, ?, ?, ?);"
self.cursor.execute(insert_data, (file_name, file_size, update_time, file_mtime))
self.conn.commit()
print("Records created successfully")
def select(self):
select_data = "SELECT * FROM ftpdown_log"
cursor = self.conn.execute(select_data)
for row in cursor:
print("id =", row[0])
print("file_name =", row[1])
print("file_size =", row[2])
print("update_time =", row[3])
print("file_mtime =", row[4], "\n")
print("Operation done successfully")
config.ini:
[FTP]
host = 192.168.0.253
username = root
password = password
port = 21
ftp_filefolder = /log/
dst_filefolder = d:/1/
项目工程结构如下:
FTPwindow.py // 实现FTP的连接,对ini配置文件的读取,指定路径中的文件夹及文件的下载
sqlite.py: //实现sqlite的数据库的创建,表的创建
config.ini: //实现为程序提供FTP地址、用户名、密码、端口号、目标指定路径、下载路径
效果如下:
以上为个人学习的记录,仅供参考和交流学习。