¿Cómo enviar un multipart/form-data
con solicitudes en python? Entiendo cómo enviar un archivo, pero no puedo entender cómo enviar los datos del formulario por este método.
python
python-2.7
multipartform-data
python-requests
agrynchuk
fuente
fuente
files
parámetro se use para hacer ambas cosas es una API muy mala. Planteé el problema titulado Envío de datos de varias partes: necesitamos una mejor API para solucionar esto. Si acepta que el uso defiles
parámetros para enviar datos de varias partes es engañoso en el mejor de los casos, solicite cambiar la API en el problema anterior.Respuestas:
Básicamente, si especifica un
files
parámetro (un diccionario),requests
enviará unamultipart/form-data
POST en lugar de unaapplication/x-www-form-urlencoded
POST. Sin embargo, no está limitado a usar archivos reales en ese diccionario:y httpbin.org te permite saber con qué encabezados publicaste; en
response.json()
tenemos:Mejor aún, puede controlar aún más el nombre de archivo, el tipo de contenido y los encabezados adicionales para cada parte mediante el uso de una tupla en lugar de una sola cadena o un objeto de bytes. Se espera que la tupla contenga entre 2 y 4 elementos; el nombre de archivo, el contenido, opcionalmente un tipo de contenido y un diccionario opcional de encabezados adicionales.
Usaría el formulario de tupla
None
como nombre de archivo, de modo que elfilename="..."
parámetro se elimine de la solicitud de esas partes:files
También puede ser una lista de tuplas de dos valores, si necesita ordenar y / o múltiples campos con el mismo nombre:Si especifica ambos
files
ydata
, entonces depende del valor dedata
lo que se utilizará para crear el cuerpo POST. Sidata
es una cadena, solo se usará; de lo contrario, ambosdata
yfiles
se usan, con los elementosdata
enumerados primero.También está el excelente
requests-toolbelt
proyecto, que incluye soporte avanzado de múltiples partes . Toma definiciones de campo en el mismo formato que elfiles
parámetro, pero a diferenciarequests
, no establece un parámetro de nombre de archivo. Además, puede transmitir la solicitud desde objetos de archivos abiertos, donderequests
primero construirá el cuerpo de la solicitud en la memoria:Los campos siguen las mismas convenciones; use una tupla con entre 2 y 4 elementos para agregar un nombre de archivo, parte tipo mime o encabezados adicionales. A diferencia del
files
parámetro, no se intenta encontrar unfilename
valor predeterminado si no usa una tupla.fuente
multipart/form-data
Tipo de contenido debe incluir el valor límite utilizado para delinquir las partes en el cuerpo de la publicación. No establecer elContent-Type
encabezado asegura que serequests
establece en el valor correcto.multipart/form-data
si el valor defiles=
es verdadero, por lo que si necesita enviar unamultipart/form-data
solicitud pero no incluye ningún archivo, puede establecer un valor verdadero pero sin sentido como{'':''}
, y establecerlodata=
con su cuerpo de solicitud. Si está haciendo esto, no proporcione elContent-Type
encabezado usted mismo;requests
lo configurará para ti. Puedes ver la verdad aquí: github.com/psf/requests/blob/…files
dict, no tienen que ser archivos (solo asegúrese de usar el formulario de tupla y establecer el nombre de archivo enNone
). Mejor aún, use elrequests_toolbelt
proyecto.Desde que se escribieron las respuestas anteriores, las solicitudes han cambiado. Eche un vistazo al hilo de errores en Github para obtener más detalles y este comentario como 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 es una cadena o una tupla de 2, 3 o 4 longitudes, como se describe en la sección PUBLICAR un archivo codificado en varias partes en las solicitudes Inicio rápido:En lo anterior, la tupla se compone de la siguiente manera:
Si el valor es solo una cadena, el nombre del archivo será el mismo que la clave, como se muestra a continuación:
Si el valor es una tupla y la primera entrada es
None
la propiedad del nombre de archivo no se incluirá:fuente
name
yfilename
pero también tener múltiples campos con el mismo nombre?files
tupla ya no funciona: es necesario utilizarrequests.post
data
parámetro en lugar de enviar archivos no additionnalmultipart/form-data
parámetrosNone
lugar de una cadena vacía parece funcionarDebe usar el
files
parámetro para enviar una solicitud POST de formulario multiparte incluso cuando no necesite cargar ningún archivo.De la fuente original de solicitudes :
La parte relevante es:
file-tuple can be a
2-tuple
,3-tuple
or a
4-tuple
.Con base en lo anterior, la solicitud de formulario multiparte más simple que incluye tanto archivos para cargar como campos de formulario se verá así:
☝ Tenga en cuenta que
None
es el primer argumento en la tupla para campos de texto sin formato: este 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 que pasanNone
como primer parámetro es necesario para que los datos se envíen .Múltiples campos con el mismo nombre.
Si necesita publicar múltiples campos con el mismo nombre, en lugar de un diccionario, puede definir su carga útil como una lista (o una tupla) de tuplas:
API de solicitudes de transmisión
Si la API anterior no es lo suficientemente pitónica para usted, entonces considere usar el toolbelt de solicitudes (
pip install requests_toolbelt
), que es una extensión del módulo de solicitudes principales que proporciona soporte para la transmisión de carga de archivos, así como el MultipartEncoder que se puede usar en lugar defiles
, y que también permite Usted define la carga útil como un diccionario, tupla o lista.MultipartEncoder
se puede usar tanto para solicitudes de varias partes con o sin campos de carga reales. Debe asignarse aldata
parámetro.Si necesita enviar varios campos con el mismo nombre, o si el orden de los campos del formulario es importante, puede usar una tupla o una lista en lugar de un diccionario:
fuente
file.py
se encuentra en la misma carpeta que su script.None
lugar de una cadena vacía. Entonces las solicitudes no incluirán un nombre de archivo en absoluto. Así que en lugar deContent-Disposition: form-data; name="action"; filename=""
eso seráContent-Disposition: form-data; name="action"
. Para mí, esto era fundamental para que el servidor aceptara esos campos como campos de formulario y no como archivos.Aquí está el fragmento de código simple para cargar un solo archivo con parámetros adicionales mediante solicitudes:
Tenga en cuenta que no necesita especificar explícitamente ningún tipo de contenido.
NOTA: Quería comentar una de las respuestas anteriores, pero no pude debido a la baja reputación, por lo que redacté una nueva respuesta aquí.
fuente
Debe usar el
name
atributo del archivo de carga que se encuentra en el HTML del sitio. Ejemplo:Lo ves
name="image">
? Puede encontrarlo en el HTML de un sitio para cargar el archivo. Debe usarlo para cargar el archivo conMultipart/form-data
guión:
Aquí, en lugar de la imagen, agregue el nombre del archivo de carga en HTML
Si la carga requiere hacer clic en el botón para cargar, puede usar así:
Entonces comienza la solicitud
Y listo, archivo cargado con éxito
fuente
Enviar clave y valor multiparte / datos de formulario
comando curl:
solicitudes de Python : solicitudes POST más complicadas :
Enviar archivo multipart / form-data
comando curl:
solicitudes de Python : PUBLICA un archivo codificado en varias partes :
eso es todo.
fuente
Aquí está el fragmento de Python que necesita para cargar un archivo único grande como datos de formulario multiparte. Con el middleware NodeJs Multer ejecutándose en el lado del servidor.
Para el lado del servidor, consulte la documentación del multer en: https://github.com/expressjs/multer aquí, el campo single ('fieldName') se usa para aceptar un solo archivo, como en:
fuente