¿Cómo enviar un multipart/form-data
con solicitudes 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.¿Cómo enviar un "multipart/form-data" con solicitudes en python?
Respuesta
Básicamente, si especifica un parámetro files
(un diccionario), entonces requests
enviará un POST multipart/form-data
en lugar de un POST application/x-www-form-urlencoded
. No está limitado a la utilización de los archivos reales en ese diccionario, sin embargo:
>>> import requests
>>> response = requests.post('http://httpbin.org/post', files=dict(foo='bar'))
>>> response.status_code
200
y httpbin.org le permite saber lo que los ficheros de encabezado informado con; 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 puede ser una lista de tuplas de dos valores, si es necesario 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
, entonces depende del valor de data
lo que se usará para crear el cuerpo POST. Si data
es una cadena, solo se usará; de lo contrario, se usan data
y files
, con los elementos en data
listados primero.
Esto codificará cualquier cosa enviada a 'archivos' como un parámetro de archivo real en la codificación multiparte. Esto no creará una forma estricta sino un formulario con todos los parámetros de archivo. Ver [esto] (https://github.com/kennethreitz/requests/issues/1081) para referencia. –
@ sigmavirus24: la API de solicitudes ha evolucionado desde que publiqué esto; déjame investigar si esto necesita una actualización ahora. En cualquier caso, esta esquina de la API [ha estado necesitando una revisión por un tiempo ahora] (https://github.com/kennethreitz/requests/issues/935). –
disculpas. StackOverflow pone esto cerca de la parte superior y olvido las preguntas de reorganización y tengo que mirar las fechas respondidas/solicitadas. –
Como se escribieron las respuestas anteriores, las solicitudes han cambiado. Eche un vistazo a bug thread at Github para más detalles y this comment para un ejemplo.
En resumen, el parámetro de archivos toma dict
con la clave que es el nombre del campo de formulario y el valor es una cadena o una tupla de 2, 3 o 4 longitudes, como se describe en la sección POST a Multipart-Encoded File en las solicitudes 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 sólo una cadena, el nombre del archivo será la misma que la clave, como en el siguiente:
>>> 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 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
¿Qué sucede si necesita distinguir 'nombre' y' nombre_archivo' pero también tiene varios campos con el mismo nombre? – Michael
Tengo un problema similar a @Michael. ¿Puedes echar un vistazo a la pregunta y sugerir algo? [link] (http://stackoverflow.com/questions/30683352/how-to-upload-multipart-encode-file-and-form-data-as-a-payload) – Shaardool
¿Alguien resolvió este problema al tener múltiples campos? con el mismo nombre? – user3131037
Es necesario utilizar el parámetro files
para enviar una solicitud POST de formulario de varias partes, incluso cuando no es necesario cargar ningún archivo.
Desde el original requests fuente:
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 solicitud impreso de varias copias más simple que incluye tanto los datos para cargar y campos de formulario se vería así:
multipart_form_data = {
'file1': open('myfile.zip', 'rb'),
'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)
☝ Nota la cadena vacía como el primer elemento en la tupla para campos de texto plano: este es un marcador de posición para el campo de nombre de archivo que solo se usa para cargar archivos, pero para el campo de texto, el marcador de posición vacío debe estar presente en orden para los datos que se enviarán
Si esta API no es suficiente Pythonic para usted, o si usted necesita para enviar múltiples campos con el mismo nombre, y luego considerar el uso de requests toolbelt (
pip install requests_toolbelt
) que es una extensión del módulo
core requests que proporciona soporte para archivos cargar la transmisión, así como
MultipartEncoder que se puede utilizar en lugar de
files
, y que acepta parámetros como diccionarios y tuplas.
MultipartEncoder
puede utilizarse tanto para solicitudes de varias partes con o sin campos de carga reales. Debe asignarse al parámetro data
.
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
multipart_data = MultipartEncoder(
fields={
# a file upload field
'file': ('file.py', open('file.py', '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, entonces una tupla o una lista se puede utilizar en lugar de un diccionario, es decir:
multipart_data = MultipartEncoder(
fields=(
('action', 'store'),
('path', '/path1'),
('path', '/path2'),
('path', '/path3'),
)
)
Gracias por esto. El orden de las llaves fue importante para mí y esto ayudó mucho. – Splendor
Increíble. Inexplicablemente, una API con la que estoy trabajando requiere 2 valores diferentes para la misma clave. Esto es increíble. Gracias. – ajon
@ccpizza, ¿qué significa realmente esta línea? > "('file.py', open ('file.py', 'rb'), 'text/plain')". No funciona para mí :( –
- 1. ¿Cómo enviar solicitudes consecutivas con HTTP keep-alive en node.js?
- 2. Prueba MultipartFormData en Play 2.0 FakeRequest
- 3. Python XMLRPC con solicitudes simultáneas
- 4. ¿Método ideal para enviar múltiples solicitudes HTTP sobre Python?
- 5. Python Solicitudes y sesiones persistentes
- 6. Solicitudes de firma con python-oauth2
- 7. Solicitudes concurrentes en Appengine Python
- 8. ¿Cómo recibir solicitudes xml y enviar respuesta xml en php?
- 9. Proxies con el módulo 'Solicitudes' de Python
- 10. python enviar POST con cabecera
- 11. cómo enviar solicitudes de red al servidor (geográficamente) más cercano
- 12. Enviar encabezados en python
- 13. Cómo enviar una solicitud oauth con python-oauth2
- 14. ¿Cómo enviar solicitudes HTTPS al host con certificado de servidor no confiable en iPhone Simulator?
- 15. Enviar invitaciones a reuniones con Python
- 16. Cómo enviar autenticación HTTP con Selenium python-binding webdriver
- 17. ¿Es posible enviar "solicitudes" de LDAP a través de telnet?
- 18. python: cómo enviar correo con TO, CC y BCC?
- 19. ¿Cómo enviar un formulario con AJAX/JSON?
- 20. python: urllib2 cómo enviar cookies con la solicitud de urlopen
- 21. Error de proxy de Python con la biblioteca de solicitudes
- 22. Safari no permite solicitudes AJAX después de enviar formularios?
- 23. ¿Cómo puedo enviar encabezados personalizados con URLRequest
- 24. solicitudes http con powershell
- 25. Enviar un archivo a través de sockets en Python
- 26. ¿es mejor o agrupar mis solicitudes de AJAX o enviar todas las solicitudes por separado?
- 27. Python - ¿Cómo enviar un correo electrónico a utf-8?
- 28. ¿Cómo puedo enviar correos electrónicos usando Python?
- 29. Cabeceras personalizadas con solicitudes de video HTML5
- 30. Cómo reducir un número de solicitudes AJAX para un chat?
tu pregunta no es muy clara. ¿Qué quieres lograr? ¿Desea enviar "multipart/form-data" sin una carga de archivo en el formulario? –
El hecho de que el parámetro 'files' se use para hacer ambas cosas es una API muy mala. Planteé el tema titulado [Envío de datos de varias partes: necesitamos una mejor API] (https://github.com/kennethreitz/requests/issues/935) para solucionarlo. Si acepta que el uso del parámetro 'files' para enviar datos de mulitpart es engañoso en el mejor de los casos, solicite cambiar la API en el problema anterior. –
@PiotrDobrogost ese problema está cerrado. No anime a las personas a comentar sobre cuestiones cerradas, relevantes o no. –