Using ftplib to upload a file to a server....
Andy Jewell
andy at wild-flower.co.uk
Thu Jun 19 17:22:37 EDT 2003
On Thursday 19 Jun 2003 2:56 pm, Francois Meehan wrote:
> Hi all,
>
> Please excuse my "newbiness", but I can't get python to upload a file using
> ftplib, basically I don't make sense of the transfercmd.
>
> I can connect, return a file listing, but could not find upload example on
> the net.
>
> Could someone provide me an example? Or is there an easier modules to use
> for FTP file transfer?
>
> Francois
You may find this interesting (I'm not making any claims as to *how*
interesting, tho).
I'm using this (in an incrementally modified state) at the moment to transfre
files to/from AS/400 and HP-UX ftp servers, and it's working fine...
Hope it helps
-andyj
-----------------8<---------------
import ftplib
import os
localfilecache="c:/temp/ftpcache/"
class ftpfile(file):
""" url,mode="r",buffering=-1
FTP aware file object which delegates "normal" file operations
to the superclass.
If the file name begins "ftp://", FTP mode is enabled.
In FTP mode, where reading of the file is required, the file is
first downloaded from the remote host, and where writing is
required, the file is uploaded when it is closed.
NOTE THAT FTP READS AND WRITES ARE PERFORMED ON A LOCAL COPY
"""
def __init__(self,name,mode="r",buffering=-1):
if not name.startswith("ftp://"):
return super(ftpfile).__init__(name,mode,buffering)
self.filemode=mode
self.decodeurl(name)
self.localfilename=os.path.join(localfilecache,
self.host,self.user,
self.path,self.filename)
localpath=os.path.join(localfilecache,
self.host,self.user,
self.path)
if not os.path.exists(localpath):
os.makedirs(localpath)
# Decide if we need to download the file first
if self.filemode[0] not in ["w","wb"]:
self.downloadfile(name,self.filemode)
# Short-circuit our close() method if file doesn't need
# to be uploaded
if self.filemode in ["r","rb"]:
self.close=super(ftpfile,self).close
#self.localfilehandle=file(self.localfilename,self.filemode)
return super(ftpfile,self).__init__(self.localfilename,mode,buffering)
def close(self):
# ... then upload it
ftpconn=ftplib.FTP(self.host,self.user,self.passwd,None)
ftpconn.cwd(self.path)
try:
ftpconn.delete(self.filename)
except:
pass
super(ftpfile,self).close()
self.localfilehandle=file(self.localfilename,"r")
if "b" in self.mode:
ftpconn.storbinary("STOR "+self.filename,self.localfilehandle)
else:
ftpconn.storlines("STOR "+self.filename,self.localfilehandle)
ftpconn.close()
# Close the file...
self.localfilehandle.close()
def downloadfile(self,name,mode):
# Use correct file mode
if "b" in mode:
retr=ftplib.FTP.retrbinary
self.writer=self.binwriter
localmode="wb"
else:
retr=ftplib.FTP.retrlines
self.writer=self.txtwriter
localmode="w"
# Download the file
if os.path.exists(self.localfilename):
os.remove(self.localfilename)
self.localfilehandle=file(self.localfilename,localmode)
ftpconn=ftplib.FTP(self.host,self.user,self.passwd)
ftpconn.cwd(self.path)
if "b" in mode:
ftpconn.retrbinary("RETR "+self.filename,self.binwriter)
else:
ftpconn.retrlines("RETR "+self.filename,self.txtwriter)
ftpconn.close()
self.localfilehandle.close()
def decodeurl(self,url):
""" decodes an ftp url into its component fields:
ftp://[user[:passwd]@]host[:port]/path/filename
/ / / / / /
| | | | | lastslash
| | | | firstslash
| | at portcolon
| colon
6
"""
# Sanity check:
if not url.startswith("ftp://"):
raise "Malformed url:",url
# Do we have a user:passwd pair?
at=url.find("@",6)
colon=url.find(":",6)
portcolon=url.find(":",at)
if at == -1:
at=6
self.user=None
self.passwd=None
else:
if colon == -1:
colon=at
self.user=url[6:colon]
self.passwd=url[colon+1:at]
if self.passwd == "":
self.passwd=None
firstslash=url.find("/",at)
if firstslash == -1:
raise "Malformed url:",url
if portcolon !=-1:
self.host=url[at+1:portcolon]
self.port=url[portcolon:firstslash]
else:
self.host=url[at+1:firstslash]
self.port=":21"
lastslash=url.rfind("/")
if lastslash == -1:
raise "Malformed url:",url
self.filename=url[lastslash+1:]
self.path=url[firstslash:lastslash]
print self.user+":"+self.passwd+"."
print self.host,self.path,self.filename
def binwriter(self,block):
self.localfilehandle.write(block)
def txtwriter(self,line):
self.localfilehandle.write(line+"\n")
def write(self,string):
print "Writing",repr(string)
super(ftpfile,self).write(string)
More information about the Python-list
mailing list