我正在尝试实现最能描述为“HTTP API 的 FTP 接口”的内容。本质上,有一个现有的 REST API 可用于管理站点的用户文件,并且我正在构建一个中介服务器,将该 API 重新公开为 FTP 服务器。因此,您可以使用 Filezilla 登录并列出您的文件、上传新文件、删除旧文件等。
我正在尝试这样做twisted.protocols.ftp
对于 (FTP) 服务器,以及twisted.web.client
对于 (HTTP) 客户端。
我遇到的问题是,当用户尝试下载文件时,该文件从 HTTP 响应“流式传输”到我的 FTP 响应。上传类似。
最直接的方法是从 HTTP 服务器下载整个文件,然后将内容发送给用户。这样做的问题是任何给定的文件都可能有很多 GB 大(例如驱动器映像、ISO 文件等)。不过,使用这种方法,在我从 API 下载文件和将其发送给用户之间,文件的内容将保存在内存中 - 不好。
所以我的解决方案是尝试“流式传输”它 - 当我从 API 的 HTTP 响应中获取数据块时,我只想转身并将这些数据块发送给 FTP 用户。Seems直截了当。
对于我的“自定义 FTP 功能”,我使用的是ftp.FTPShell
。这个的读法,openForReading
,返回一个 Deferred 并通过以下实现触发IReadFile http://twistedmatrix.com/documents/10.1.0/api/twisted.protocols.ftp.IReadFile.html.
下面是我的“streaming HTTP”的(初始的、简单的)实现。我用fetch
函数来设置 HTTP 请求,并且我传入的回调会随着从响应中获得的每个块而被调用。
我想我可以使用某种两端缓冲区对象在 HTTP 和 FTP 之间传输块,方法是将缓冲区对象用作 FTP 所需的类文件对象ftp._FileReader http://twistedmatrix.com/documents/10.1.0/api/twisted.protocols.ftp._FileReader.html,但这很快就被证明是行不通的,因为来自send
调用几乎立即关闭缓冲区(因为它返回一个空字符串,因为还没有数据可供读取等)。因此,我什至在开始接收 HTTP 响应块之前就“发送”了空文件。
我很接近,但错过了什么吗?我完全走错路了吗?是我想做的事really不可能(我非常怀疑)?
from twisted.web import client
import urlparse
class HTTPStreamer(client.HTTPPageGetter):
def __init__(self):
self.callbacks = []
def addHandleResponsePartCallback(self, callback):
self.callbacks.append(callback)
def handleResponsePart(self, data):
for cb in self.callbacks:
cb(data)
client.HTTPPageGetter.handleResponsePart(self, data)
class HTTPStreamerFactory(client.HTTPClientFactory):
protocol = HTTPStreamer
def __init__(self, *args, **kwargs):
client.HTTPClientFactory.__init__(self, *args, **kwargs)
self.callbacks = []
def addChunkCallback(self, callback):
self.callbacks.append(callback)
def buildProtocol(self, addr):
p = client.HTTPClientFactory.buildProtocol(self, addr)
for cb in self.callbacks:
p.addHandleResponsePartCallback(cb)
return p
def fetch(url, callback):
parsed = urlparse.urlsplit(url)
f = HTTPStreamerFactory(parsed.path)
f.addChunkCallback(callback)
from twisted.internet import reactor
reactor.connectTCP(parsed.hostname, parsed.port or 80, f)
顺便说一句,这只是我使用 Twisted 的第二天 - 我昨天花了大部分时间阅读 Dave Peticolas 的书扭曲简介 http://krondo.com/blog/?page_id=1327,这是一个很好的起点,即使基于旧版本的twisted。
这就是说,我may做错事。