尝试通过HTTP在Twisted中发送文件时,我遇到了一个相当烦人的问题。我是Python的新手(因为这是我第一次尝试除Hello World之外的任何其他事情)。
现在,我很确定当FileSender发送不兼容UTF-8的二进制数据时会出现问题。在通过网络移动图像,视频,可执行二进制文件等文件时,这似乎是一件相当普遍的事情。
在我看来,在初始化时,Twisted缓冲区被初始化为""
,这里(我可能在这里很奇怪)是一个UTF-8(或者你的Python的默认字符编码是什么)字符串?...然后,当新数据被添加到缓冲区时,旧缓冲区(UTF-8)与新缓冲区(呃......其他二进制编码?)连接,结果是:
Unhandled Error
Traceback (most recent call last):
Failure: exceptions.RuntimeError: Producer was not unregistered for /vfs/videos/thevid.avi
Unhandled Error
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/twisted/python/log.py", line 84, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File "/usr/lib/python2.7/dist-packages/twisted/python/log.py", line 69, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "/usr/lib/python2.7/dist-packages/twisted/python/context.py", line 118, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/usr/lib/python2.7/dist-packages/twisted/python/context.py", line 81, in callWithContext
return func(*args,**kw)
--- <exception caught here> ---
File "/usr/lib/python2.7/dist-packages/twisted/internet/selectreactor.py", line 146, in _doReadOrWrite
why = getattr(selectable, method)()
File "/usr/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 428, in doWrite
result = abstract.FileDescriptor.doWrite(self)
File "/usr/lib/python2.7/dist-packages/twisted/internet/abstract.py", line 199, in doWrite
self.dataBuffer = buffer(self.dataBuffer, self.offset) + "".join(self._tempDataBuffer)
File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
exceptions.UnicodeDecodeError: 'utf8' codec can't decode byte 0xd3 in position 6: invalid continuation byte
Unhandled Error
Traceback (most recent call last):
Failure: exceptions.RuntimeError: Producer was not unregistered for /vfs/videos/thevid.avi
当然必须有一种方法可靠地设置缓冲区进行二进制数据传输?我的文件发送功能代码如下。我正在使用TxJSONRPC来创建和管理服务器(render
方法除外,它被覆盖以处理不仅仅是RPC)。如果需要更多信息(例如关于Request对象或Reactor,我可以去挖掘)。
注意:我很清楚我没有错误处理程序,但此刻对我来说并不重要。一旦我可靠地传输文件,就会添加错误处理!
def writeFile(self, request, location):
# Setup headers (mime type, filename)
request.setHeader('Content-Type', mimetypes.guess_type("file://" + location))
request.setHeader('Content-Disposition', "attachment; filename=" + path.basename(location))
# Open file
handle = open(location, "rb")
# Setup transfer (then cleanup etc)
d = FileSender().beginFileTransfer(handle, request)
def fileFinished(ignored):
handle.close()
request.finish()
d.addCallback(fileFinished).addErrback(fileFinished)