!/bin/env python
import os, sys, ftplib
from getpass import getpass
from mimetypes import guess_type, add_type
defaultSite = 'home.rmi.net'
defaultRdir = '.'
defaultUser = 'lutz'
def configTransfer(site=defaultSite, rdir=defaultRdir, user=defaultUser):
class cf: pass
cf.nonpassive = False # passive FTP on by default in 2.1+
cf.remotesite = site # transfer to/from this site
cf.remotedir = rdir # and this dir ('.' means acct root)
cf.remoteuser = user
cf.localdir = (len(sys.argv) > 1 and sys.argv[1]) or '.'
cf.cleanall = input('Clean target directory first? ')[:1] in ['y','Y']
cf.remotepass = getpass(
'Password for %s on %s:' % (cf.remoteuser, cf.remotesite))
return cf
def isTextKind(remotename, trace=True):
add_type('text/x-python-win', '.pyw') # not in tables
mimetype, encoding = guess_type(remotename, strict=False) # allow extras
mimetype = mimetype or '?/?' # type unknown?
maintype = mimetype.split('/')[0] # get first part
if trace: print(maintype, encoding or '')
return maintype == 'text' and encoding == None # not compressed
def connectFtp(cf):
print('connecting...')
connection = ftplib.FTP(cf.remotesite) # connect to FTP site
connection.login(cf.remoteuser, cf.remotepass) # log in as user/password
connection.cwd(cf.remotedir) # cd to directory to xfer
if cf.nonpassive: # force active mode FTP
connection.set_pasv(False) # most servers do passive
return connection
def cleanLocals(cf):
if cf.cleanall:
for localname in os.listdir(cf.localdir): # local dirlisting
try: # local file delete
print('deleting local', localname)
os.remove(os.path.join(cf.localdir, localname))
except:
print('cannot delete local', localname)
def downloadAll(cf, connection):
remotefiles = connection.nlst() # nlst is remote listing
for remotename in remotefiles:
if remotename in ('.', '..'): continue
localpath = os.path.join(cf.localdir, remotename)
print('downloading', remotename, 'to', localpath, 'as', end=' ')
if isTextKind(remotename):
# use text mode xfer
localfile = open(localpath, 'w', encoding=connection.encoding)
def callback(line): localfile.write(line + '\n')
connection.retrlines('RETR ' + remotename, callback)
else:
# use binary mode xfer
localfile = open(localpath, 'wb')
connection.retrbinary('RETR ' + remotename, localfile.write)
localfile.close()
connection.quit()
print('Done:', len(remotefiles), 'files downloaded.')
if name == 'main':
cf = configTransfer()
conn = connectFtp(cf)
cleanLocals(cf) # don't delete if can't connect
downloadAll(cf, conn)
----------------------------------------------------上传所有文件到FTP服务器 封装类
!/bin/env python
import os
from downloadflat_modular import configTransfer, connectFtp, isTextKind
def cleanRemotes(cf, connection):
if cf.cleanall:
for remotename in connection.nlst(): # remote dir listing
try: # remote file delete
print('deleting remote', remotename) # skips . and .. exc
connection.delete(remotename)
except:
print('cannot delete remote', remotename)
def uploadAll(cf, connection):
localfiles = os.listdir(cf.localdir) # listdir is local listing
for localname in localfiles:
localpath = os.path.join(cf.localdir, localname)
print('uploading', localpath, 'to', localname, 'as', end=' ')
if isTextKind(localname):
# use text mode xfer
localfile = open(localpath, 'rb')
connection.storlines('STOR ' + localname, localfile)
else:
# use binary mode xfer
localfile = open(localpath, 'rb')
connection.storbinary('STOR ' + localname, localfile)
localfile.close()
connection.quit()
print('Done:', len(localfiles), 'files uploaded.')
if name == 'main':
cf = configTransfer(site='learning-python.com', rdir='books', user='lutz')
conn = connectFtp(cf)
cleanRemotes(cf, conn)
uploadAll(cf, conn)