【问题标题】:Twisted - Simple file completed event for FTP serverTwisted - FTP 服务器的简单文件完成事件
【发布时间】:2012-03-20 15:47:03
【问题描述】:

我想在一些基本的 FTP 服务器上使用 twisted,just like this example:

from twisted.protocols.ftp  import FTPFactory, FTPRealm
from twisted.cred.portal    import Portal
from twisted.cred.checkers  import AllowAnonymousAccess, FilePasswordDB
from twisted.internet       import reactor

#pass.dat looks like this:
# jeff:bozo
# grimmtooth:bozo2

p = Portal(FTPRealm('./'), (AllowAnonymousAccess(), FilePasswordDB("pass.dat")))
f = FTPFactory(p)
reactor.listenTCP(21, f)
reactor.run()

...通过一个简单的自定义:我想在文件上传 (STOR) 成功完成时触发一个事件,以便我的自定义代码可以充分处理此文件。

我没有找到可以帮助我执行此操作的 FTPFactory 或 FTP 文档。我应该重载 FTP 对象还是其他对象?如何连接所有东西?

我过去用twisted 做过简单的自定义HTTP 服务器,这很容易,但我几乎找不到关于FTP 的资料。

【问题讨论】:

    标签: python ftp twisted ftp-server


    【解决方案1】:

    首先,这只是对 Rakis 答案的修改。没有他的回答,这将不存在。他的一个对我的设置不起作用。也可能只是 API 发生了变化,因为这是 5 年后的事了。

    class MyFTP (ftp.FTP):
    
        def ftp_STOR(self, path):
    
            d = super(MyFTP, self).ftp_STOR(path)
    
            def onStorComplete(d):
                print 'STORED', repr(d), path
                return d
    
            d.addCallback(onStorComplete)
    
            return d
    
    f = ftp.FTPFactory( some_portal_object )
    f.protocol = MyFTP
    

    【讨论】:

    • 我无法对此进行测试(它已经 5 年了),所以我只会相信你并接受这个答案。
    【解决方案2】:

    看起来下面的方法可以解决问题

    from twisted.protocols import ftp
    
    class MyFTP (ftp.FTP):
        def ftp_STOR(self, path):
            d = super(MyFTP, self).ftp_STOR(path)
    
            d.addCallback( lambda _: self.onStorComplete(path) )
    
            return d
    
        def onStorComplete(self, path):
            # XXX your code here
    
     f = ftp.FTPFactory( some_portal_object )
     f.protocol = MyFTP
    

    【讨论】:

    • 它没有;在文件传输开始之前调用回调(并且传输正在循环,使用 Filezilla)。另外,我的文件没有被存储。 :\
    • ftp_STOR 肯定会返回一个仅在传输完成后触发的延迟。您的程序可能还有其他问题。
    • 我基于我在我的问题上链接的示例。我注意到所有写入尝试都失败了。我将对此进行进一步调查……
    • 显然该示例没有写入磁盘。 :( 我正在考虑等待 FTP api+docs 成熟并采取池化方法。
    • 我敢打赌,Ekevoo 的示例没有写入磁盘的原因是因为他像 ln 一样使用FTPRealm('./')。 36 的例子显示。这将设置FTPRealm 类的anonymousRoot,但将userHome 值保留为默认值/home(如source 所示,这似乎是一个糟糕的设计,即never really fixed)。我建议使用FTPRealm(anonymousRoot='./', userHome='./someDir')