type requests form example delete data content python python-2.7 multipartform-data python-requests

requests - ¿Cómo enviar un "multipart/form-data" con solicitudes en python?



requests request python (4)

¿Cómo enviar un multipart/form-data con peticiones en python? Cómo entiendo cómo enviar un archivo, pero no puedo entender cómo enviar los datos del formulario mediante este método.


Básicamente, si especifica un parámetro de files (un diccionario), las requests enviarán una POST multipart/form-data lugar de una application/x-www-form-urlencoded POST. Sin embargo, no está limitado a usar archivos reales en ese diccionario:

>>> import requests >>> response = requests.post(''http://httpbin.org/post'', files=dict(foo=''bar'')) >>> response.status_code 200

y httpbin.org le permite saber con qué encabezados ha publicado; en response.json() tenemos:

>>> from pprint import pprint >>> pprint(response.json()[''headers'']) {u''Accept'': u''*/*'', u''Accept-Encoding'': u''gzip, deflate, compress'', u''Connection'': u''close'', u''Content-Length'': u''141'', u''Content-Type'': u''multipart/form-data; boundary=33b4531a79be4b278de5f5688fab7701'', u''Host'': u''httpbin.org'', u''User-Agent'': u''python-requests/2.2.1 CPython/2.7.6 Darwin/13.2.0'', u''X-Request-Id'': u''eaf6baf8-fc3d-456b-b17d-e8219ccef1b1''}

files también pueden ser una lista de tuplas de dos valores, si necesita ordenar y / o múltiples campos con el mismo nombre:

requests.post(''http://requestb.in/xucj9exu'', files=((''foo'', ''bar''), (''spam'', ''eggs'')))

Si especifica files y data , depende del valor de los data que se usarán para crear el cuerpo POST. Si los data son una cadena, solo se usará; de lo contrario files se utilizan tanto los data como los files , con los elementos en los data primero.


Debe usar el atributo de name del archivo de carga que está en el HTML del sitio. Ejemplo:

autocomplete="off" name="image">

¿Ves name="image"> ? Puede encontrarlo en el HTML de un sitio para cargar el archivo. Debe usarlo para cargar el archivo con Multipart/form-data

guión:

import requests site = ''https://prnt.sc/upload.php'' # the site where you upload the file filename = ''image.jpg'' # name example

Aquí, en el lugar de la imagen, agregue el nombre del archivo de carga en HTML

up = {''image'':(filename, open(filename, ''rb''), "multipart/form-data")}

Si la carga requiere hacer clic en el botón para cargarla, puede usarla así:

data = { "Button" : "Submit", }

Entonces comienza la solicitud

request = requests.post(site, files=up, data=data)

Y hecho, archivo cargado con éxito


Debe usar el parámetro de files para enviar una solicitud POST de formulario multiparte incluso cuando no necesite cargar ningún archivo.

Desde la fuente original de requests :

def request(method, url, **kwargs): """Constructs and sends a :class:`Request <Request>`. ... :param files: (optional) Dictionary of ``''name'': file-like-objects`` (or ``{''name'': file-tuple}``) for multipart encoding upload. ``file-tuple`` can be a 2-tuple ``(''filename'', fileobj)``, 3-tuple ``(''filename'', fileobj, ''content_type'')`` or a 4-tuple ``(''filename'', fileobj, ''content_type'', custom_headers)``, where ``''content-type''`` is a string defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers to add for the file.

La parte relevante es: file-tuple can be a 2-tuple , 3-tuple or a 4-tuple .

En función de lo anterior, la solicitud de formulario multiparte más simple que incluye ambos archivos para cargar y campos de formulario se verá así:

multipart_form_data = { ''file2'': (''custom_file_name.zip'', open(''myfile.zip'', ''rb'')), ''action'': ('''', ''store''), ''path'': ('''', ''/path1'') } response = requests.post(''https://httpbin.org/post'', files=multipart_form_data) print(response.content)

Observe la cadena vacía como primer argumento en la tupla para campos de texto plano: es un marcador de posición para el campo de nombre de archivo que solo se usa para cargar archivos, pero para los campos de texto todavía se requiere el marcador de posición vacío para enviar los datos .

Si esta API no es suficientemente pitónica para usted o si necesita publicar varios campos con el mismo nombre, considere usar las solicitudes toolbelt ( pip install requests_toolbelt ) que es una extensión del módulo de solicitudes principales que brinda soporte para la transmisión de carga de archivos como así como MultipartEncoder que puede usarse en lugar de files y que acepta parámetros tanto en diccionarios como en tuplas.

MultipartEncoder se puede usar tanto para solicitudes de varias partes con o sin campos de carga reales. Debe asignarse al parámetro de data .

import requests from requests_toolbelt.multipart.encoder import MultipartEncoder multipart_data = MultipartEncoder( fields={ # a file upload field ''file'': (''file.py'', open(''file.zip'', ''rb''), ''text/plain'') # plain text fields ''field0'': ''value0'', ''field1'': ''value1'', } ) response = requests.post(''http://httpbin.org/post'', data=multipart_data, headers={''Content-Type'': multipart_data.content_type})

Si necesita enviar varios campos con el mismo nombre, o si el orden de los campos del formulario es importante, se puede usar una tupla o una lista en lugar de un diccionario, es decir:

multipart_data = MultipartEncoder( fields=( (''action'', ''ingest''), (''item'', ''spam''), (''item'', ''sausage''), (''item'', ''eggs''), ) )


Desde que se escribieron las respuestas anteriores, las solicitudes han cambiado. Eche un vistazo al this para más detalles y este comentario para un ejemplo.

En resumen, el parámetro de archivos toma un dict con la clave que es el nombre del campo de formulario y el valor que es una cadena o una tupla de 2, 3 o 4 longitudes, como se describe en la sección POST un Archivo codificado en varias partes en el solicita inicio rápido:

>>> url = ''http://httpbin.org/post'' >>> files = {''file'': (''report.xls'', open(''report.xls'', ''rb''), ''application/vnd.ms-excel'', {''Expires'': ''0''})}

En lo anterior, la tupla se compone de la siguiente manera:

(filename, data, content_type, headers)

Si el valor es solo una cadena, el nombre del archivo será el mismo que el de la clave, como se muestra a continuación:

>>> files = {''obvius_session_id'': ''72c2b6f406cdabd578c5fd7598557c52''} Content-Disposition: form-data; name="obvius_session_id"; filename="obvius_session_id" Content-Type: application/octet-stream 72c2b6f406cdabd578c5fd7598557c52

Si el valor es una tupla y la primera entrada es None la propiedad del nombre de archivo no se incluirá:

>>> files = {''obvius_session_id'': (None, ''72c2b6f406cdabd578c5fd7598557c52'')} Content-Disposition: form-data; name="obvius_session_id" Content-Type: application/octet-stream 72c2b6f406cdabd578c5fd7598557c52