[Twisted-Python] [usage] FTPClient uploading multiple files

tarjei tarjei at nu.no
Mon Jul 9 10:54:06 EDT 2007


Hi, after spending a few hours grooking the FTPClient API (with good
help from Exarkun on IRC) I thought I'd post the fruits of my work.

I hope this may help someone. If the code is usefull enough feel free to
add it to the examples in the docs.

If you see errors or got ideas on how this could be done different, feel
free to answer :-)

regards,
Tarjei


class FtpFileSave(object):

    """
    A class for uploading multiple files to a ftp host.
    Usage:

    ftp = FtpFileSave(ftpFiles=['/etc/passwd', '/etc/magic'],
_pass="something",
    _username = "something", host="localhost")
    ftp.save(somecallback, errorcallback)

    This will upload multiple files to the ftpserver.
    @caveat 1: as it stands the class does not change directory or
anything like that before uploading the files.
    This should be easy to add though.
    """

    _pass = ""
    _username = ""
    port = 21
    host = "localhost"

    def __init__(self, **kwargs):
        """Create a ftpfilesaver using the ftp client fromtwisted
        @param ftpFiles list of paths to the files to upload.
        """
        self.__dict__.update(kwargs)
        self.nextfile = 0

    def save(self, success,error):
        """Uploads a set of tiles to the ftpserver.
        @param success: the callback to be called on success
        @param error:   the callback to be called on error
        """
        self.success = success

        FTPClient.debug = True
        creator = ClientCreator(reactor, FTPClient, self._username,
                    self._pass, passive=True)
        defer = creator.connectTCP(self.host,self.port)
        self.error = error
        defer.addCallback(self.connectionMade).addErrback(self.error)
        return defer

    def connectionMade(self,ftpClient):
        "Checks if there are more files to upload and uploads them.
        The main point with this method is that you have to collect the
defereds of each command
        and wait until they succeed.
        "
        deffereds = []
        "We'll need the client to do a disconnect later"
        self.client = ftpClient
        " Create defereds for each of the different files to be uploaded"
        for upfile in self.ftpFiles:
            if not os.path.exists(upfile):
                raise Exception("File %s not found" % upfile)
            store, finish = ftpClient.storeFile("./%s" %
os.path.basename(upfile))
            finish.addCallback(self.end).addErrback(self.error)
            store.addCallback(self.send_file).addErrback(self.error)
            deffereds.append(store)
            deffereds.append(finish)
        return defer.gatherResults(deffereds)

    def end(self, ftpResult):
        """Close the connection when all files have been uploaded.
            @param ftpResult a list of the protocol info we get. Not
very interesting.
            @todo: check the list for errors.
        """
        if (len(self.ftpFiles) <= self.nextfile):
            self.client.quit()
            self.client.transport.loseConnection()
            return defer.succeed(self.success())
        return

    def send_file(self, sender):
        """Open and send the file
        """
        #print "Storefile %d : %s"  % (self.nextfile,
self.ftpFiles[self.nextfile])
        filename = self.ftpFiles[self.nextfile]
        fp = open(filename,'r')
        sender.transport.write(fp.read())
        sender.finish()
        "increase the nextfile count so end() knows when it's done"
        self.nextfile += 1







More information about the Twisted-Python mailing list