からPOSTを使用してファイルを送信しますか?PythonスクリプトからPOSTを使用してファイルを送信する方法はありますPythonスクリプト
答えて
はい。 urllib2
モジュールを使用し、multipart/form-data
コンテンツタイプを使用してエンコードします。ここでは、始めるためにいくつかのサンプルコードがある - それはちょうどアップロードファイルよりも少しですが、あなたはそれを読んで、それがどのように動作するかを見ることができるはず:
user_agent = "image uploader"
default_message = "Image $current of $total"
import logging
import os
from os.path import abspath, isabs, isdir, isfile, join
import random
import string
import sys
import mimetypes
import urllib2
import httplib
import time
import re
def random_string (length):
return ''.join (random.choice (string.letters) for ii in range (length + 1))
def encode_multipart_data (data, files):
boundary = random_string (30)
def get_content_type (filename):
return mimetypes.guess_type (filename)[0] or 'application/octet-stream'
def encode_field (field_name):
return ('--' + boundary,
'Content-Disposition: form-data; name="%s"' % field_name,
'', str (data [field_name]))
def encode_file (field_name):
filename = files [field_name]
return ('--' + boundary,
'Content-Disposition: form-data; name="%s"; filename="%s"' % (field_name, filename),
'Content-Type: %s' % get_content_type(filename),
'', open (filename, 'rb').read())
lines = []
for name in data:
lines.extend (encode_field (name))
for name in files:
lines.extend (encode_file (name))
lines.extend (('--%s--' % boundary, ''))
body = '\r\n'.join (lines)
headers = {'content-type': 'multipart/form-data; boundary=' + boundary,
'content-length': str (len (body))}
return body, headers
def send_post (url, data, files):
req = urllib2.Request (url)
connection = httplib.HTTPConnection (req.get_host())
connection.request ('POST', req.get_selector(),
*encode_multipart_data (data, files))
response = connection.getresponse()
logging.debug ('response = %s', response.read())
logging.debug ('Code: %s %s', response.status, response.reason)
def make_upload_file (server, thread, delay = 15, message = None,
username = None, email = None, password = None):
delay = max (int (delay or '0'), 15)
def upload_file (path, current, total):
assert isabs (path)
assert isfile (path)
logging.debug ('Uploading %r to %r', path, server)
message_template = string.Template (message or default_message)
data = {'MAX_FILE_SIZE': '3145728',
'sub': '',
'mode': 'regist',
'com': message_template.safe_substitute (current = current, total = total),
'resto': thread,
'name': username or '',
'email': email or '',
'pwd': password or random_string (20),}
files = {'upfile': path}
send_post (server, data, files)
logging.info ('Uploaded %r', path)
rand_delay = random.randint (delay, delay + 5)
logging.debug ('Sleeping for %.2f seconds------------------------------\n\n', rand_delay)
time.sleep (rand_delay)
return upload_file
def upload_directory (path, upload_file):
assert isabs (path)
assert isdir (path)
matching_filenames = []
file_matcher = re.compile (r'\.(?:jpe?g|gif|png)$', re.IGNORECASE)
for dirpath, dirnames, filenames in os.walk (path):
for name in filenames:
file_path = join (dirpath, name)
logging.debug ('Testing file_path %r', file_path)
if file_matcher.search (file_path):
matching_filenames.append (file_path)
else:
logging.info ('Ignoring non-image file %r', path)
total_count = len (matching_filenames)
for index, file_path in enumerate (matching_filenames):
upload_file (file_path, index + 1, total_count)
def run_upload (options, paths):
upload_file = make_upload_file (**options)
for arg in paths:
path = abspath (arg)
if isdir (path):
upload_directory (path, upload_file)
elif isfile (path):
upload_file (path)
else:
logging.error ('No such path: %r' % path)
logging.info ('Done!')
Chris Atleeさんのposterライブラリは、この機能(特に便利機能poster.encode.multipart_encode()
)のために本当にうまく機能します。ボーナスとして、ファイル全体をメモリにロードせずに大きなファイルのストリーミングをサポートします。 Python issue 3244も参照してください。
ファイルオブジェクトに直接urlopenを使用することを止める唯一の事実は、組み込みファイルオブジェクトにlenの定義がないことです。簡単な方法は、urlopenに正しいファイルを提供するサブクラスを作成することです。 以下のファイルのContent-Typeヘッダーも変更しました。
>>> with open('report.xls', 'rb') as f: r = requests.post('http://httpbin.org/post', files={'report.xls': f})
それだ:http://docs.python-requests.org/en/latest/user/quickstart/#post-a-multipart-encoded-file
要求の中から
import os
import urllib2
class EnhancedFile(file):
def __init__(self, *args, **keyws):
file.__init__(self, *args, **keyws)
def __len__(self):
return int(os.fstat(self.fileno())[6])
theFile = EnhancedFile('a.xml', 'r')
theUrl = "http://example.com/abcde"
theHeaders= {'Content-Type': 'text/xml'}
theRequest = urllib2.Request(theUrl, theFile, theHeaders)
response = urllib2.urlopen(theRequest)
theFile.close()
for line in response:
print line
@robert Python2.7でコードをテストしますが、機能しません。 urlopen(Request(theUrl、theFile、...))は、ファイルの内容を通常の投稿と同じようにエンコードしますが、正しい書式フィールドは指定できません。 私は変わったurlopen(theUrl、urlencode({'serverside_field_name':EnhancedFile( 'my_file.txt')})))を試しても、間違った内容のファイルを(もちろん!)my_file.txtとしてアップロードします'、0x00D6B718>でモード' r '。 私は何かを見逃しましたか? – RayLuo
答えをありがとう。上記のコードを使用すると、PUTリクエストを使用して2.2 GBのRAWイメージファイルをWebサーバーに転送しました。 –
は、マルチパートエンコードされたファイルをアップロードすることが非常に簡単になります。私は冗談ではありません - これはコードの1行です。ファイルが送信されました。確認しましょう:
>>> r.text
{
"origin": "179.13.100.4",
"files": {
"report.xls": "<censored...binary...data>"
},
"form": {},
"url": "http://httpbin.org/post",
"args": {},
"headers": {
"Content-Length": "3196",
"Accept-Encoding": "identity, deflate, compress, gzip",
"Accept": "*/*",
"User-Agent": "python-requests/0.8.0",
"Host": "httpbin.org:80",
"Content-Type": "multipart/form-data; boundary=127.0.0.1.502.21746.1321131593.786.1"
},
"data": ""
}
ファイルサイズが1.5 MB未満の場合、私は同じことを試しています。それ以外の場合は、エラーを投げてください.. [こちら]を見てください(http://stackoverflow.com/questions/20217348/requests-post-files-upload-large-file-more-than-1-5-mb-python )。 –
何をしようとしているのは、私がうまくやったリクエストを使っていくつかのサイトにログインすることですが、今はログイン後にビデオをアップロードしたいのですが、フォームに提出するフィールドが異なります。だから、どのように私はビデオの説明、ビデオのタイトルなど – TaraGurung
のような値を渡す必要がありますあなたはおそらく '( 'report.xls'、 'rb')を開くと' f:r = requests.post( 'http:// httpbin.org/post '、files = {' report.xls ':f}) 'を実行して、オープンした後でファイルを再度閉じます。 – Hjulle
非常に大きなマルチパートファイルはpythonリクエストでは処理されません。
ドキュメントでは、requests-toolbelt
に見てお勧めします。そのドキュメントから
Here's the pertinent page。私は私のために残りのAPIとその作業をDjangoのテストしようとしています
def visit_v2(device_code, camera_code):
image1 = MultipartParam.from_file("files", "/home/yuzx/1.txt")
image2 = MultipartParam.from_file("files", "/home/yuzx/2.txt")
datagen, headers = multipart_encode([('device_code', device_code), ('position', 3), ('person_data', person_data), image1, image2])
print "".join(datagen)
if server_port == 80:
port_str = ""
else:
port_str = ":%s" % (server_port,)
url_str = "http://" + server_ip + port_str + "/adopen/device/visit_v2"
headers['nothing'] = 'nothing'
request = urllib2.Request(url_str, datagen, headers)
try:
response = urllib2.urlopen(request)
resp = response.read()
print "http_status =", response.code
result = json.loads(resp)
print resp
return result
except urllib2.HTTPError, e:
print "http_status =", e.code
print e.read()
:Windows上でこのコードを使用している間のpython 2.6.6で
def test_upload_file(self):
filename = "/Users/Ranvijay/tests/test_price_matrix.csv"
data = {'file': open(filename, 'rb')}
client = APIClient()
# client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
response = client.post(reverse('price-matrix-csv'), data, format='multipart')
print response
self.assertEqual(response.status_code, status.HTTP_200_OK)
私はマルチパート境界の解析でエラーを取得しました。これを行うには、string.lettersからstring.ascii_lettersに変更する必要がありました(http://stackoverflow.com/questions/2823316/generate-a-random-letter-in-python/2823331#2823331)。境界上の要件は、ここで説明されていますhttp://stackoverflow.com/questions/147451/what-are-valid-characters-for-creating-a-multipart-form-boundary/147467#147467 –
run_uploadを({」を呼び出しますサーバ ':'」、 '糸': ''}、パス= [ '/パス/に/ file.txtを'])この行でエラーが発生し : upload_file(パス) 3つのパラメータを必要とする "ファイルをアップロードする" ため は、私は、ファイルのアップロードに対処する方法を示しています何の例がありません – Radian