通常、チャンクされたファイルを読み取り、途中で進行状況を報告するストリーミング データソース (ジェネレーター) を構築します ( kennethreitz/requests#663を参照してください。これは、要求ファイル API では機能しません。要求はストリーミング アップロードをサポートしていないためです ( kennethreitz/requests#295を参照) – アップロードするファイルは、処理を開始する前にメモリ内で完了する必要があります。
ただし、JF Sebastian が以前に証明したように、要求はジェネレーターからコンテンツをストリーミングできますが、このジェネレーターは、マルチパート エンコーディングと境界を含む完全なデータストリームを生成する必要があります。これがポスターの出番です。
poster はもともとpythons urllib2で使用するために書かれており、マルチパート リクエストのストリーミング生成をサポートし、進行状況を示します。Posters Homepage は、urllib2 と一緒に使用する例を提供していますが、実際には urllib2 を使用したくありません。urllib2 を使用して HTTP 基本認証を行う方法については、このサンプル コードを確認してください。恐ろしい。
したがって、進行状況を追跡してファイルのアップロードを行うリクエストと一緒に poster を使用したいと考えています。方法は次のとおりです。
# load requests-module, a streamlined http-client lib
import requests
# load posters encode-function
from poster.encode import multipart_encode
# an adapter which makes the multipart-generator issued by poster accessable to requests
# based upon code from http://stackoverflow.com/a/13911048/1659732
class IterableToFileAdapter(object):
def __init__(self, iterable):
self.iterator = iter(iterable)
self.length = iterable.total
def read(self, size=-1):
return next(self.iterator, b'')
def __len__(self):
return self.length
# define a helper function simulating the interface of posters multipart_encode()-function
# but wrapping its generator with the file-like adapter
def multipart_encode_for_requests(params, boundary=None, cb=None):
datagen, headers = multipart_encode(params, boundary, cb)
return IterableToFileAdapter(datagen), headers
# this is your progress callback
def progress(param, current, total):
if not param:
return
# check out http://tcd.netinf.eu/doc/classnilib_1_1encode_1_1MultipartParam.html
# for a complete list of the properties param provides to you
print "{0} ({1}) - {2:d}/{3:d} - {4:.2f}%".format(param.name, param.filename, current, total, float(current)/float(total)*100)
# generate headers and gata-generator an a requests-compatible format
# and provide our progress-callback
datagen, headers = multipart_encode_for_requests({
"input_file": open('recordings/really-large.mp4', "rb"),
"another_input_file": open('recordings/even-larger.mp4', "rb"),
"field": "value",
"another_field": "another_value",
}, cb=progress)
# use the requests-lib to issue a post-request with out data attached
r = requests.post(
'https://httpbin.org/post',
auth=('user', 'password'),
data=datagen,
headers=headers
)
# show response-code and -body
print r, r.text