带有长时间网络请求的进度条
在我正在开发的一个django应用中,我刚刚添加了将多个文件(总大小从50MB开始)打包成一个zip文件的功能。目前,我的做法是这样的:
get files to zip
zip all files
send HTML response
显然,在第二行压缩文件时,会导致用户需要等待很长时间。我该怎么做才能让这个过程对用户更友好呢?虽然有一个进度条是最好的选择,但即使只是返回一个静态页面,上面写着“请稍等”之类的提示也不错。
任何想法和建议都非常欢迎。
4 个回答
你可以使用一个“日志文件”来记录压缩的文件,以及还有多少文件没有处理。
具体的步骤可以这样做:
- 先计算一下文件的数量,把这个数字写进一个文本文件,格式可以是 totalfiles.filesprocessed。
- 每当你压缩一个文件,就更新这个日志文件。
所以,如果你需要压缩3个文件,日志文件的内容会变成:
3.0 -> begin, no file still processed
3.1 -> 1 file on 3 processed, 33% task complete
3.2 -> 2 file on 3 processed, 66% task complete
3.3 -> 3 file on 3 processed, 100% task complete
然后用一个简单的ajax函数(设置一个时间间隔)每秒检查一次日志文件。
在Python中,打开、读取和写入这样的小文件应该非常快,但如果有很多用户同时在做这个,可能会导致一些请求的问题。不过,你显然需要为每个请求创建一个日志文件,文件名可以随机生成,任务完成后再删除。
一个问题是,为了让ajax读取日志文件,你每次更新时都需要在Python中打开和关闭文件处理器。
最后,为了更准确地显示进度,你甚至可以用文件大小来代替文件数量作为参数。
有趣的事实:你可以用进度条来让用户觉得事情进展得比实际快。
http://www.chrisharrison.net/projects/progressbars/index.html
你要记住,显示进度条可能不是个好主意,因为这样可能会导致超时,或者让你的服务器因为同时处理太多请求而受不了。
可以把压缩的任务放到队列里,然后通过某种方式通知用户,比如发邮件,告诉他们这个过程已经完成。
你可以看看 django-lineup。
你的代码大概会像这样:
from lineup import registry
from lineup import _debug
def create_archive(queue_id, queue):
queue.set_param("zip_link", _create_archive(resource = queue.context_object, user = queue.user))
return queue
def create_archive_callback(queue_id, queue):
_send_email_notification(subject = queue.get_param("zip_link"), user = queue.user)
return queue
registry.register_job('create_archive', create_archive, callback = create_archive_callback)
在你的视图中,创建排队的任务可以这样做:
from lineup.factory import JobFactory
j = JobFactory()
j.create_job(self, 'create_archive', request.user, your_resource_object_containing_files_to_zip, { 'extra_param': 'value' })
然后运行你的队列处理器(可能是在一个屏幕会话里):
./manage.py run_queue
哦,关于这个话题,你可能还会对 估算压缩文件创建时间 感兴趣。我在那儿得到了很不错的答案。