-
Notifications
You must be signed in to change notification settings - Fork 28
/
pyftpclient.py
125 lines (97 loc) · 3.99 KB
/
pyftpclient.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# coding=utf-8
__author__ = 'Roman Podlinov'
import threading
import logging
import ftplib
import socket
import time
def setInterval(interval, times = -1):
# This will be the actual decorator,
# with fixed interval and times parameter
def outer_wrap(function):
# This will be the function to be
# called
def wrap(*args, **kwargs):
stop = threading.Event()
# This is another function to be executed
# in a different thread to simulate setInterval
def inner_wrap():
i = 0
while i != times and not stop.isSet():
stop.wait(interval)
function(*args, **kwargs)
i += 1
t = threading.Timer(0, inner_wrap)
t.daemon = True
t.start()
return stop
return wrap
return outer_wrap
class PyFTPclient:
def __init__(self, host, port = 21, login = 'anonymous', passwd = 'anonymous', monitor_interval = 30):
self.host = host
self.port = port
self.login = login
self.passwd = passwd
self.monitor_interval = monitor_interval
self.ptr = None
self.max_attempts = 15
self.waiting = True
def DownloadFile(self, dst_filename, local_filename = None):
res = ''
if local_filename is None:
local_filename = dst_filename
with open(local_filename, 'w+b') as f:
self.ptr = f.tell()
@setInterval(self.monitor_interval)
def monitor():
if not self.waiting:
i = f.tell()
if self.ptr < i:
logging.debug("%d - %0.1f Kb/s" % (i, (i-self.ptr)/(1024*self.monitor_interval)))
self.ptr = i
else:
ftp.close()
def connect():
ftp.connect(self.host, self.port)
ftp.login(self.login, self.passwd)
# optimize socket params for download task
ftp.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
ftp.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 75)
ftp.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
ftp = ftplib.FTP()
ftp.set_debuglevel(2)
ftp.set_pasv(True)
connect()
ftp.voidcmd('TYPE I')
dst_filesize = ftp.size(dst_filename)
mon = monitor()
while dst_filesize > f.tell():
try:
connect()
self.waiting = False
# retrieve file from position where we were disconnected
res = ftp.retrbinary('RETR %s' % dst_filename, f.write) if f.tell() == 0 else \
ftp.retrbinary('RETR %s' % dst_filename, f.write, rest=f.tell())
except:
self.max_attempts -= 1
if self.max_attempts == 0:
mon.set()
logging.exception('')
raise
self.waiting = True
logging.info('waiting 30 sec...')
time.sleep(30)
logging.info('reconnect')
mon.set() #stop monitor
ftp.close()
if not res.startswith('226 Transfer complete'):
logging.error('Downloaded file {0} is not full.'.format(dst_filename))
# os.remove(local_filename)
return None
return 1
if __name__ == "__main__":
# logging.basicConfig(filename='/var/log/dreamly.log',format='%(asctime)s %(levelname)s: %(message)s',level=logging.DEBUG)
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=cfg.logging.level)
obj = PyFTPclient('192.168.0.59', port = 2121, login = 'test', passwd = 'testftp')
obj.DownloadFile('USAHD-8974-20131013-0300-0330.ts')