【发布时间】:2011-08-20 23:14:11
【问题描述】:
我正在通过 POST 将带有 urllib2 的相当大的文件上传到服务器端脚本。我想显示一个显示当前上传进度的进度指示器。是否有 urllib2 提供的挂钩或回调允许我监控上传进度?我知道您可以使用对连接的 read() 方法的连续调用来进行下载,但我没有看到 write() 方法,您只需将数据添加到请求中。
【问题讨论】:
标签: python http urllib2 http-post
我正在通过 POST 将带有 urllib2 的相当大的文件上传到服务器端脚本。我想显示一个显示当前上传进度的进度指示器。是否有 urllib2 提供的挂钩或回调允许我监控上传进度?我知道您可以使用对连接的 read() 方法的连续调用来进行下载,但我没有看到 write() 方法,您只需将数据添加到请求中。
【问题讨论】:
标签: python http urllib2 http-post
这是可能的,但您需要做一些事情:
__len__ 属性使 urllib2 子系统将文件句柄向下传递给 httplib,该属性使 len(data) 返回正确的大小,用于填充 Content-Length 标头。read() 方法:当 httplib 调用 read() 时,您的回调将被调用,让您计算百分比并更新进度条。这可以与任何类似文件的对象一起使用,但我已经包装了 file 以展示它如何与从磁盘流式传输的非常大的文件一起使用:
import os, urllib2
from cStringIO import StringIO
class Progress(object):
def __init__(self):
self._seen = 0.0
def update(self, total, size, name):
self._seen += size
pct = (self._seen / total) * 100.0
print '%s progress: %.2f' % (name, pct)
class file_with_callback(file):
def __init__(self, path, mode, callback, *args):
file.__init__(self, path, mode)
self.seek(0, os.SEEK_END)
self._total = self.tell()
self.seek(0)
self._callback = callback
self._args = args
def __len__(self):
return self._total
def read(self, size):
data = file.read(self, size)
self._callback(self._total, len(data), *self._args)
return data
path = 'large_file.txt'
progress = Progress()
stream = file_with_callback(path, 'rb', progress.update, path)
req = urllib2.Request(url, stream)
res = urllib2.urlopen(req)
输出:
large_file.txt progress: 0.68
large_file.txt progress: 1.36
large_file.txt progress: 2.04
large_file.txt progress: 2.72
large_file.txt progress: 3.40
...
large_file.txt progress: 99.20
large_file.txt progress: 99.87
large_file.txt progress: 100.00
【讨论】:
urllib2AbstractHTTPHandler.do_request_()和httplib HttpConnect._send_request()中使用,其中len(<file obj>)被调用来设置Content-length头部。
requests 2.0.0 has streaming uploads。这意味着您可以使用生成器生成小块并打印块之间的进度。
【讨论】:
我认为这是不可能的,但pycurl does have upload/download progress callbacks你可以使用。
【讨论】:
poster 支持这个
import json
import os
import sys
import urllib2
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
def _upload_progress(param, current, total):
sys.stdout.write(
"\r{} - {:.0f}% "
.format(param.name,
(float(current) / float(total)) * 100.0))
sys.stdout.flush()
def upload(request_resource, large_file_path):
register_openers()
with open(large_file_path, 'r') as large_file:
request_data, request_headers = multipart_encode(
[('file', largs_file)],
cb=_upload_progress)
request_headers.update({
'X-HockeyAppToken': 'we use this for hockeyapp upload'
})
upload_request = urllib2.Request(request_resource,
request_data,
request_headers)
upload_connection = urllib2.urlopen(upload_request)
upload_response = json.load(upload_connection)
print "Done"
【讨论】: