http://blog.ityao.com/archives/59
Flash Player的文件上传很是让人憋火。除了PHP,CF,Asp.net和它配合良好–不会有差错。
Python下就没有那么方便了。
我曾经在web.py下,试了几天,后来没法子用Django才搞定的。
总是有莫名其妙的问题。
我在Twisted的邮件列表里发了一通:
I’ve been trying to upload files to twisted.web2 backend(FileSaver) with Adobe Flex and I am always getting IOError.
(code see below)
After some sniffing work, I found the error messages returned by twisted.web2:
Unexpected data on same line as boundary: ‘–’
I believe this flex app works with php backend. So this might be with twisted.web2 or flash player’s malformed post data.
It seems the twisted error comes from fileupload.py:
(I added 2 prints)
def _readBoundaryLine(self):
print "_readBoundaryLine"
line = self.stream.readline(size=1024)
if isinstance(line, defer.Deferred):
line = defer.waitForDeferred(line)
yield line
line = line.getResult()
print line
if line == "--\r\n":
# THE END!
yield False
return
elif line != "\r\n":
raise MimeFormatError("Unexpected data on same line as boundary: %r" % (line,))
yield True
return
_readBoundaryLine = defer.deferredGenerator(_readBoundaryLine)
with html uploading form, it outputs:
2009-08-20 23:06:08+0800 [-] _readBoundaryLine
2009-08-20 23:06:08+0800 [-] –
2009-08-20 23:06:08+0800 [-]
2009-08-20 23:06:08+0800 [-]
2009-08-20 23:06:08+0800 [-] FileUpload
but with flex uploading:
2009-08-20 23:06:27+0800 [-] _readBoundaryLine
2009-08-20 23:06:27+0800 [-]
2009-08-20 23:06:27+0800 [-]
2009-08-20 23:06:27+0800 [-] _readBoundaryLine
2009-08-20 23:06:27+0800 [-]
2009-08-20 23:06:27+0800 [-]
2009-08-20 23:06:27+0800 [-] _readBoundaryLine
2009-08-20 23:06:27+0800 [-] –
Same file, different posted data.
Any ideas?
Does this happen to be a bug, or is there any way to walk around this?
My testing code:
python code:
from twisted.web2 import http_headers, resource, \
static, server, channel, http, responsecode
from twisted.python import util
FORMHTML = """
<html>
<p>for test</p>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="FileUpload" />
<input type="submit" value="Upload"/>
</form>
</html>
"""
class MyFileSaver(static.FileSaver):
"""for test only"""
def render(self, req):
print req, '--------'
if req.files:
for fieldName in req.files:
print fieldName
return http.Response(responsecode.OK, {}, stream='ok')
class Toplevel(resource.Resource):
addSlash = True
def render(self, ctx):
return http.Response(stream=FORMHTML)
child_upload = MyFileSaver(util.sibpath(__file__, ''),
expectedFields=['FileUpload'],
allowedTypes=(
http_headers.MimeType('image', 'jpeg'),
http_headers.MimeType('image', 'png'),
http_headers.MimeType('image', 'gif'),
)
)
child_swf = static.File(util.sibpath(__file__, 'FileUpload.swf'))
site = server.Site(Toplevel())
# Standard twisted application Boilerplate
from twisted.application import service, strports
application = service.Application("demoserver")
s = strports.service('tcp:8080', channel.HTTPFactory(site))
s.setServiceParent(application)
My flex code:
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/09/21/uploading-files-in-flex-using-the-filereference-class/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white"
creationComplete="init();">
<mx:Script>
<![CDATA[
private var fileRef:FileReference;
private const FILE_UPLOAD_URL:String = "http://127.0.0.1:8080/upload";
private function init():void {
fileRef = new FileReference();
fileRef.addEventListener(Event.SELECT, fileRef_select);
fileRef.addEventListener(ProgressEvent.PROGRESS, fileRef_progress);
fileRef.addEventListener(Event.COMPLETE, fileRef_complete);
fileRef.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSec);
}
private function browseAndUpload():void {
fileRef.browse();
message.text = "";
}
private function ioErrorHandler(event:IOErrorEvent):void {
trace(event);
}
private function onSec(event:SecurityErrorEvent):void{
trace(event);
}
private function fileRef_select(evt:Event):void {
try {
message.text = "size (bytes): " + numberFormatter.format(fileRef.size);
var req:URLRequest = new URLRequest();
req.url = FILE_UPLOAD_URL;
req.method = URLRequestMethod.POST;
fileRef.upload(req, "FileUpload");
} catch (err:Error) {
message.text = "ERROR: zero-byte file";
}
}
private function fileRef_progress(evt:ProgressEvent):void {
progressBar.visible = true;
}
private function fileRef_complete(evt:Event):void {
message.text += " (complete)";
progressBar.visible = false;
}
]]>
</mx:Script>
<mx:NumberFormatter id="numberFormatter" />
<mx:Button label="Upload file"
click="browseAndUpload();" />
<mx:Label id="message" />
<mx:ProgressBar id="progressBar"
indeterminate="true"
visible="false" />
</mx:Application>
解决方法:
暂时没有,但是有一个patch:
http://twistedmatrix.com/trac/ticket/2113
一起哭吧。。。
3 条评论
虽然不会python,还是顶一个!
额,过几天和你一起哭
咋的了?你开始用python了?