他の回答がすでに指摘しているようrequests
に、マルチパートでエンコードされたファイルをメモリにロードせずに POSTing をサポートしていません。
multipart/form-data を使用してメモリにロードせずに大きなファイルをアップロードするには、次を使用できますposter
。
#!/usr/bin/env python
import sys
from urllib2 import Request, urlopen
from poster.encode import multipart_encode # $ pip install poster
from poster.streaminghttp import register_openers
register_openers() # install openers globally
def report_progress(param, current, total):
sys.stderr.write("\r%03d%% of %d" % (int(1e2*current/total + .5), total))
url = 'http://example.com/path/'
params = {'file': open(sys.argv[1], "rb"), 'name': 'upload test'}
response = urlopen(Request(url, *multipart_encode(params, cb=report_progress)))
print response.read()
ローカル ファイルの代わりに GET 応答オブジェクトを許可するように適応させることができます。
import posixpath
import sys
from urllib import unquote
from urllib2 import Request, urlopen
from urlparse import urlsplit
from poster.encode import MultipartParam, multipart_encode # pip install poster
from poster.streaminghttp import register_openers
register_openers() # install openers globally
class MultipartParamNoReset(MultipartParam):
def reset(self):
pass # do nothing (to allow self.fileobj without seek() method)
get_url = 'http://example.com/bigfile'
post_url = 'http://example.com/path/'
get_response = urlopen(get_url)
param = MultipartParamNoReset(
name='file',
filename=posixpath.basename(unquote(urlsplit(get_url).path)), #XXX \ bslash
filetype=get_response.headers['Content-Type'],
filesize=int(get_response.headers['Content-Length']),
fileobj=get_response)
params = [('name', 'upload test'), param]
datagen, headers = multipart_encode(params, cb=report_progress)
post_response = urlopen(Request(post_url, datagen, headers))
print post_response.read()
このソリューションではContent-Length
、GET 応答に有効なヘッダー (既知のファイル サイズ) が必要です。ファイル サイズが不明な場合は、チャンク転送エンコーディングを使用して multipart/form-data コンテンツをアップロードできます。ライブラリurllib3.filepost
に同梱されているものを使用して同様のソリューションを実装できます。requests
poster