效果:
1.window开机自启动脚本。
2.自动生成配置文件到当前路径。
3.实时检测到文件夹变化,将文件通过到远程接口中,且文件进行分类备份到其他文件夹下。
4.实时发送心跳包,确保不会宕机。
5.重试机制@retry(已废除)
6.未解决BUG:实时删除会重复触发监测,引起modify,一次添加大量文件时会吃内存。
import datetime
import json
import os
import shutil
import time
from threading import Thread
import requests
import xlrd
from apscheduler.schedulers.blocking import BlockingScheduler
from requests_toolbelt import MultipartEncoder
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
# 读取文件夹下所有文件(不限级)
def readDir(dirPath):
if dirPath[-1] == '/':
print(u'文件夹路径末尾不能加/')
return
allFiles = []
if os.path.isdir(dirPath):
fileList = os.listdir(dirPath)
for f in fileList:
f = dirPath + '/' + f
if os.path.isdir(f):
subFiles = readDir(f)
allFiles = subFiles + allFiles # 合并当前目录与子目录的所有文件路径
else:
allFiles.append(f)
return allFiles
else:
return 'Error,not a dir'
# 创建文件夹
def createFile(file_path):
if os.path.exists(file_path) is False:
os.makedirs(file_path)
# 推送文件到接口
def post_file(file_path, PUSH_URL):
try:
data = MultipartEncoder(fields={
'propertyMessageXml': (os.path.basename(os.path.realpath(file_path)), open(file_path, 'rb'), 'text/xml')})
r = requests.post(url=PUSH_URL, data=data,
headers={'Content-Type': data.content_type, 'Connection': 'close'})
r.close()
return r.content.decode('utf8')
except:
print("推送文件失败")
# 发送心跳包
def heartbeat(url):
try:
r = requests.post(url=url, data={'msg': datetime.datetime.now()})
r.close()
except:
print("发送心跳包失败")
# 定时发送心跳包
def sendHeartbeat(url, HEARTBEAT_TIME):
scheduler = BlockingScheduler()
scheduler.add_job(heartbeat, 'interval', args=[url], seconds=int(HEARTBEAT_TIME))
scheduler.start()
def handle_file(FOLD_PATH, PUSH_URL, BACK_FOLD_BASE, SYNC_TIME):
try:
file_path_list = readDir(FOLD_PATH)
for file_path in file_path_list:
# 推送文件
result = post_file(file_path, PUSH_URL)
print("推送结果:", result)
# 对文件内容-进行分类备份
global curve_name
global test_time
try:
workbook = xlrd.open_workbook(file_path)
sheet1 = workbook.sheets()[0]
# 曲线名称
curve_name = sheet1.row(1)[1].value # 查看第2行第2列数据
# 测试时间
test_time = sheet1.row(1)[2].value.replace(" ", "").replace("/", "-").replace(":", "-")[
:10] # 查看第2行第3列数据
except BaseException as Message:
print(Message)
# 无法分类的文件
BACK_FOLD = BACK_FOLD_BASE + '\\无法分类的文件'
print(BACK_FOLD)
createFile(BACK_FOLD)
# 移动文件
shutil.copy(file_path, BACK_FOLD)
# 如果文件推送成功,就删除源文件,否则不删除,继续推送
loads = json.loads(result)
if loads['status'] == '1':
# 暂停几秒再删除,否则操作者不知道有没有把文件放进来
if SYNC_TIME:
time.sleep(int(SYNC_TIME))
os.remove(file_path)
continue
# workbook.release_resources()
# 创建文件夹
BACK_FOLD = BACK_FOLD_BASE + '\\' + curve_name + '\\' + test_time
print(BACK_FOLD)
createFile(BACK_FOLD)
# 移动文件
shutil.copy(file_path, BACK_FOLD)
# 如果文件推送成功,就删除源文件,否则不删除,继续推送
loads = json.loads(result)
if loads['status'] == '1':
if SYNC_TIME:
time.sleep(int(SYNC_TIME))
os.remove(file_path)
except BaseException as Message:
print(Message)
# 实时监测文件夹变化
class FileMonitorHandler(FileSystemEventHandler):
def __init__(self, PUSH_URL, FOLD_PATH, BACK_FOLD_BASE, SYNC_TIME) -> None:
self.PUSH_URL = PUSH_URL
self.FOLD_PATH = FOLD_PATH
self.BACK_FOLD_BASE = BACK_FOLD_BASE
self.SYNC_TIME = SYNC_TIME
super().__init__()
# 重写文件改变函数,文件改变都会触发文件夹变化
def on_modified(self, event):
print("文件发生了变化")
handle_file(self.FOLD_PATH, self.PUSH_URL, self.BACK_FOLD_BASE, self.SYNC_TIME)
# 初始化配置信息
def get_config():
config = {}
cwd = os.getcwd()
# 当前路径是否有配置文件
exists = os.path.exists(cwd + r'\config.txt')
# 如果没有配置文件就创建一个,并赋予初始值
if not exists:
config['PUSH_URL'] = 'http://localhost:8088/java/testFilePush/upload'
config['HEARTBEAT'] = 'http://localhost:8088/java/testFilePushHeartbeat/heartbeat'
config['FOLD_PATH'] = r"D:\test"
config['BACK_FOLD_BASE'] = r'D:\back'
config['HEARTBEAT_TIME'] = 60
config['SYNC_TIME'] = 3
with open(cwd + r'\config.txt', mode='w', encoding='utf-8') as f:
f.write(
r"""
# 推送地址
PUSH_URL = http://localhost:8088/java/testFilePush/upload
# 心跳地址
HEARTBEAT = http://localhost:8088/java/testFilePushHeartbeat/heartbeat
# 读取本地文件夹路径
FOLD_PATH = D:\test
# 备份基础路径
BACK_FOLD_BASE = D:\back
# 心跳周期
HEARTBEAT_TIME = 60
# 同步间隔(文件出现后多少秒同步删除)
SYNC_TIME = 3
"""
)
# 如果有配置文件就直接读取
else:
with open(cwd + r'\config.txt', mode='r', encoding='utf-8') as f:
line = f.readline()
while line:
# 去空格去换行符
line = f.readline().replace(" ", "").replace('\n', '')
if line is not None and not line.startswith('#'):
split = line.split('=')
if len(split) >= 2:
config[split[0]] = split[1]
return config
if __name__ == '__main__':
# 初始配置
config = get_config()
PUSH_URL = config['PUSH_URL']
HEARTBEAT = config['HEARTBEAT']
FOLD_PATH = config['FOLD_PATH']
BACK_FOLD_BASE = config['BACK_FOLD_BASE']
HEARTBEAT_TIME = config['HEARTBEAT_TIME']
SYNC_TIME = config['SYNC_TIME']
# 开个异步线程去执行心跳
Thread(target=sendHeartbeat, args=[HEARTBEAT, HEARTBEAT_TIME]).start()
# 实时文件夹监测
event_handler = FileMonitorHandler(PUSH_URL, FOLD_PATH, BACK_FOLD_BASE, SYNC_TIME)
observer = Observer()
observer.schedule(event_handler, path=FOLD_PATH, recursive=True) # recursive递归的
observer.start()
observer.join()