online examples python post file-upload http-post

examples - Enviar archivo usando POST desde un script de Python



python 3 examples (8)

De: http://docs.python-requests.org/en/latest/user/quickstart/#post-a-multipart-encoded-file

Solicitudes hace que sea muy sencillo cargar archivos codificados en Multipart:

with open(''report.xls'', ''rb'') as f: r = requests.post(''http://httpbin.org/post'', files={''report.xls'': f})

Eso es. No estoy bromeando, esta es una línea de código. El archivo fue enviado. Vamos a revisar:

>>> 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": "" }

¿Hay alguna manera de enviar un archivo utilizando POST desde un script de Python?


Es posible que también desee echar un vistazo a httplib2 , con examples . Me parece que usar httplib2 es más conciso que usar los módulos HTTP integrados.


Estoy intentando probar django rest api y funciona para mí:

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)


La biblioteca de poster Chris Atlee funciona muy bien para esto (particularmente la función de conveniencia poster.encode.multipart_encode() ). Como beneficio adicional, admite la transmisión de archivos de gran tamaño sin cargar todo un archivo en la memoria. Ver también Python issue 3244 .


Lo único que le impide usar urlopen directamente en un objeto de archivo es el hecho de que el objeto de archivo incorporado carece de una definición len . Una forma simple es crear una subclase, que proporciona urlopen con el archivo correcto. También modifiqué el encabezado Content-Type en el siguiente archivo.

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


Parece que las solicitudes de Python no manejan archivos extremadamente grandes de partes múltiples.

La documentación recomienda que busque en requests-toolbelt .

Aquí está la página pertinente de su documentación.


Sí. Utilizaría el módulo urllib2 y codificaría utilizando el tipo de contenido multipart/form-data . Aquí hay un código de muestra para comenzar: es algo más que la carga de archivos, pero debería poder leerlo y ver cómo funciona:

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!'')


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()