目录
1、源码
from ftplib import FTP
import os.path
class MyFTP(FTP):
def __init__(self):
print('初始化 MyFTP')
def CreateFTP(self, host, port, user, passwd):
ftp = FTP()
try:
ftp.connect(host, port, 600)
print('链接成功')
except Exception as e:
print("链接出错 => %s" % e)
return False
else:
try:
ftp.login(user, passwd)
print('登录成功')
except Exception as e:
print('登录出错 => %s' % e)
return False
return ftp
def splitpath(self, remotepath):
position = remotepath.rfind('/')
return remotepath[:position + 1], remotepath[position + 1:]
def download(self, host, port, user, passwd, remotePath, localPath, callback=None):
ftp = self.CreateFTP(host, port, user, passwd)
if not ftp:
return False
lwrite = None
conn = None
try:
ftp.set_pasv(0)
dires = self.splitpath(remotePath)
if dires[0]:
ftp.cwd(dires[0]) # 更改远程工作目录
remotefile = dires[1] # 远程文件名
print('远程工作目录: %s 远程文件名: %s' % (dires[0], dires[1]))
fsize = ftp.size(remotefile)
if fsize == 0:
return
lsize = 0
if os.path.exists(localPath):
lsize = os.stat(localPath).st_size
if lsize >= fsize: # 只处理本地文件小于远程的文件
print('本地文件已存在')
return
blocksize = 1024 * 1024
cmpsize = lsize
ftp.voidcmd('TYPE I')
conn = ftp.transfercmd('RETR %s' % remotefile, lsize)
lwrite = open(localPath, 'ab')
while True:
data = conn.recv(blocksize)
if not data:
break
lwrite.write(data)
cmpsize += len(data)
if callback:
callback(cmpsize, fsize)
print('下载进度:%.2f%%' % (float(cmpsize) / fsize * 100))
ftp.voidcmd('NOOP')
ftp.voidresp()
finally:
if lwrite:
lwrite.close()
if conn:
conn.close()
if ftp:
ftp.quit()
def upload(self, host, port, user, passwd, remotepath, localpath, callback=None):
if not os.path.exists(localpath):
print('本地文件不存在')
return
self.set_debuglevel(2)
ftp = self.CreateFTP(host, port, user, passwd)
if not ftp:
return
datasock = None
localf = None
try:
remote = self.splitpath(remotepath)
ftp.cwd(remote[0])
rsize = 0
try:
rsize = ftp.size(remote[1])
except:
pass
if (rsize == None):
rsize = 0
lsize = os.stat(localpath).st_size
print('远程文件 => %d 本地文件 => %d' % (rsize, lsize))
if rsize == lsize:
print('远程文件已存在')
return
if rsize < lsize:
localf = open(localpath, 'rb')
localf.seek(rsize)
ftp.voidcmd('TYPE I')
try:
print(remote[1])
datasock, esize = ftp.ntransfercmd("STOR %s" % remote[1], rsize)
except Exception as e:
print('ftp.ntransfercmd出错: %s' % e)
return
cmpsize = rsize
blocksize = 1024 * 1024
while True:
data = localf.read(blocksize)
if not data:
break
datasock.sendall(data)
cmpsize += len(data)
if callback:
callback(cmpsize, lsize)
print('上传进度:%.2f%%' % (float(cmpsize) / lsize * 100))
if cmpsize == lsize:
print('上传完成')
break
datasock.close()
ftp.voidcmd('NOOP')
ftp.voidresp()
finally:
if datasock:
datasock.close()
if localf:
localf.close()
if ftp:
ftp.quit()
2、调用方式
def callback(size, fsize):
print('完成 {0}/{1}'.format(size, fsize))
myFtp = MyFTP()
myFtp.download('127.0.0.1', 21, 'test', 'test', '/test/test.zip', '/test/test.zip', callback)
myFtp.upload('127.0.0.1', 21, 'test', 'test', '/test/test.zip', '/test/test.zip', callback)