[Tutor] How to make ftplib show progress while uploading a large file
Terry Carroll
carroll at tjc.com
Wed Feb 7 00:54:57 CET 2007
On Mon, 5 Feb 2007, Terry Carroll wrote:
> On Sun, 4 Feb 2007, [ISO-8859-1] Magnus Wirström wrote:
>
> > I'm workinga on a program that will upload a large file to a server
> > using ftp. I'm using ftplib to do this. I'm using a gui with wxpython
> > and i would like to have a progressbar showing in % how much have been
> > transfered. I have been googling but i can't make any sense of what i
> > have found. does anyone have a good example or could explain how to do
> > this ?
>
> Magnus --
>
> When you installed wxPython, did you also download and install the "Docs,
> Demo, Samples, etc."? There are great examples of nearly all wxPython
> dialogs, including ProgressDialog.
>
> The hard part is going to get ftplib to talk to your dialog. You're
> uploading. ftplib's download methods (retrbinary and retrlines) include a
> callback option, which would let you update the progress as you went, but
> the upload methods (storbinary and storlines) does not.[1]
>
> You could either a) install the patch from [2] on your system (or override
> storbinary and/or storlines as appropriate;
I couldn't resist. This intrigued me, partially because I will have a
similar problem in a project I have coming up. Here's an example. Most
of this is derived either from the callback patch I mentioned or from
the wxPython sample code. Very little is actual original thought.
First, set up ftplib, but with Phil Schwartz's patch to support the
callback argument.
############## begin code ###############################
import ftplib
def my_storlines(self, cmd, fp, callback=None): # patched for callback
'''Store a file in line mode.'''
CRLF = ftplib.CRLF # patched for callback
self.voidcmd('TYPE A')
conn = self.transfercmd(cmd)
while 1:
buf = fp.readline()
if not buf: break
if buf[-2:] != CRLF:
if buf[-1] in CRLF: buf = buf[:-1]
buf = buf + CRLF
conn.sendall(buf)
if callback: callback(buf) # patched for callback
conn.close()
return self.voidresp()
ftplib.FTP.storlines = my_storlines # use the patched version
############## end code ###############################
In the above, I just copied storlines out of ftplib.py, and edited it
where the "patched for callback" comments are. Note: this is for a text
file upload; the same would work for a binary file by patching storbinary
instead.
Now: set up a class that will start a wxPython ProgressDialog, but with
a callback method added:
############## begin code ###############################
class FTPProgressDialog:
def __init__(self, fname):
import wx, os
statinfo = os.stat(fname)
self.filesize = statinfo.st_size
self.so_far = 0
self.app = wx.PySimpleApp()
self.dlg = wx.ProgressDialog("Upload progress",
fname+":",
maximum = self.filesize,
style = wx.PD_APP_MODAL
| wx.PD_ELAPSED_TIME
| wx.PD_ESTIMATED_TIME
| wx.PD_REMAINING_TIME
)
def asciicallback(self, buffer):
"""
just used for testing, w/o wxPython
"""
self.so_far = self.so_far+len(buffer)-1
pct = float(self.so_far)/self.filesize
print "so far:", self.so_far, pct
return
def wxcallback(self, buffer):
self.so_far = self.so_far+len(buffer)-1
self.dlg.Update(self.so_far)
return
def close(self):
self.dlg.Destroy()
self.app.Destroy()
############## end code ###############################
The code above is not pretty; and it would have been cleaner to
have FTPProgressDialog inherit from wx.ProgressDialog. Because the
class actually starts a wx app, I'll bet you'd run into trouble if you
tried to use this in an existing wx application. But that didn't
occur to me until I was nearly done and starting to get bored. :-)
Now, to use them:
############## begin code ###############################
filename = "samplefile.txt"
ftpconn = ftplib.FTP('127.0.0.1') # small local FTP server
ftpconn.set_pasv(False) # my server doesn't support PASV
ftpconn.login()
trans_file = open(filename)
FTPprogress = FTPProgressDialog(filename)
ftpconn.storlines("STOR "+filename, trans_file, callback=FTPprogress.wxcallback)
ftpconn.quit
FTPprogress.close()
############## end code ###############################
And that, as they say, is that.
More information about the Tutor
mailing list