Cherrypy 3.2 中的多个文件上传跟踪
我有一个在 Windows 7 上运行的简单 CherryPy 3.2 Web 应用程序,它成功地允许我上传多个文件。但是,该应用程序目前不会保存上传的文件或对上传的文件执行任何特殊操作。我只想先做一些测试。无论如何,HTML 片段包含这些行
<form id="myform" action="doUpload" enctype="multipart/form-data" method="post">
<input type="file" id="files" name="files" multiple />
<input type="submit" id="button" />
</form>
相应的 CherryPy 3.2 调度程序(删除了一些代码行)以
@cherrypy.expose
def doUpload(self, **kwargs):
try:
filesUploaded = 0
for f in kwargs['files']:
self.performActualUpload(f)
filesUploaded = filesUploaded + 1
if filesUploaded < 1: self.performActualUpload(kwargs['files'])
except KeyError:
pass
self.performActualUpload() 方法开始,该方法有一个非常简单的循环,仅计算读取的字节数并打印总数。 (我没有使用任何日志记录功能;我只是将所有输出转储到 Windows 7 命令提示符)。
size = 0
while True:
try:
data = f.file.read(8192)
if not data:
break
size += len(data)
except AttributeError:
size = 0
print ("total bytes transferred is {}".format(size))
我发现 self.performActualUpload() 的输出仅在所有文件上传后生成,而不是在传输期间生成。我想要的是监视传输中的字节数,以便我可以使用不断增长的进度条或不断变化的数字总数来更新 HTML 字段。
我通过谷歌搜索偶然发现了这个线程 http ://old.nabble.com/File-upload-stats-in-CP-3.0-td13499294.html 讨论了在 CherryPy 3.0 中跟踪文件上传统计信息,但在 3.2 版本中不 HTTP 框架。
我知道必须使用 jQuery POST 之类的方法连续调用 upload_stats() 来向 CherryPy 3.2 询问最新的上传统计信息。我还意识到我需要创建一个 FieldStorage 对象(具有重写的 make_file() 方法的对象)。然而,我无法弄清楚如何成功实例化 FieldStorage 对象。我在 doUpload() 调度程序中尝试了以下代码行,
lcHDRS = {}
for key, val in cherrypy.request.headers.items():
lcHDRS[key.lower()] = val
formFields = FieldStorage(fp=cherrypy.request.rfile,
headers=lcHDRS,
environ={'REQUEST_METHOD':'POST'},
keep_blank_values=True)
结果收到此错误消息
ValueError: <cherrypy.wsgiserver.KnownLengthRFile object at 0x0000000003959198>
should return bytes, got str
KnownLengthRFile 是类似文件对象的包装器。我尝试将 str 转换为字节,但没有成功。所以,我完全不知道如何从这一点出发。诚然,我目前对 Python 3.2 和 CherryPy 3.2 的了解相当有限。
有人可以帮助我吗?再次,我尝试在 调整代码片段http://old.nabble.com/File-upload-stats-in-CP-3.0-td13499294.html 到 CherryPy 3.2 Web 应用程序中。还有一些围绕整个 AJAX 交互的问题(即调用 upload_stats()、接收 JSON 实体并解析它),但我将在下次讨论。谢谢。
I have a simplistic CherryPy 3.2 web application, running on Windows 7, that successfully allows me to upload multiple files. The application doesn't save or do anything special with the uploaded files at the moment, however. I just want to do some testing first. Anyways, the HTML snippet includes these lines
<form id="myform" action="doUpload" enctype="multipart/form-data" method="post">
<input type="file" id="files" name="files" multiple />
<input type="submit" id="button" />
</form>
The corresponding CherryPy 3.2 dispatcher (with some lines of code removed) begins with
@cherrypy.expose
def doUpload(self, **kwargs):
try:
filesUploaded = 0
for f in kwargs['files']:
self.performActualUpload(f)
filesUploaded = filesUploaded + 1
if filesUploaded < 1: self.performActualUpload(kwargs['files'])
except KeyError:
pass
The self.performActualUpload() method has a very simple loop that just counts the number of bytes read and prints the total. (I haven't used any logging features; I just dump all output to the Windows 7 command prompt).
size = 0
while True:
try:
data = f.file.read(8192)
if not data:
break
size += len(data)
except AttributeError:
size = 0
print ("total bytes transferred is {}".format(size))
What I discovered is that the output from self.performActualUpload() is only generated after all files have been uploaded and not during the transfer. What I want is to monitor the amount of bytes in transit so I can update an HTML field with either a growing progress bar or just an ever-changing numeric total.
I've trawled through Google searches and stumbled upon this thread http://old.nabble.com/File-upload-stats-in-CP-3.0-td13499294.html that talks about tracking file upload stats in CherryPy 3.0 but not with version 3.2 of the HTTP framework.
I understand that upload_stats() will have to be continuously called with something like a jQuery POST to ask CherryPy 3.2 for the latest upload statistics. I also realise I need to create a FieldStorage object (the one with an overridden make_file() method). What I cannot figure out, however, is how to successfully instantiate the FieldStorage object. I tried the following lines of code in my doUpload() dispatcher
lcHDRS = {}
for key, val in cherrypy.request.headers.items():
lcHDRS[key.lower()] = val
formFields = FieldStorage(fp=cherrypy.request.rfile,
headers=lcHDRS,
environ={'REQUEST_METHOD':'POST'},
keep_blank_values=True)
only to receive this error message
ValueError: <cherrypy.wsgiserver.KnownLengthRFile object at 0x0000000003959198>
should return bytes, got str
KnownLengthRFile is a wrapper around a file-like object. I tried to convert the str into bytes but that didn't work. So, I'm at a total loss on how to proceed from this point. Admittedly, my knowledge of Python 3.2 and CherryPy 3.2 is quite limited at the moment.
Is there someone out there who can help me? Again, I'm trying to adapt the code fragments over at http://old.nabble.com/File-upload-stats-in-CP-3.0-td13499294.html into a CherryPy 3.2 web application. There's also some questions surrounding the whole AJAX interaction (i.e., calling upload_stats(), receiving a JSON entity and parsing it) but I'll reserve that for another time. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用yield并返回具有实际上传文件大小的流。
您可以在此处使用cherrypy检查产量: http://www.cherrypy.org/wiki/ReturnVsYield
这是收益率适合的情况之一。
Use yield and return a streaming with the actual uploaded file size.
You can check yield with cherrypy here: http://www.cherrypy.org/wiki/ReturnVsYield
This is one of the cases where yield fits.