Respuestas Binarias y Archivos
Descubre cómo trabajar con datos no textuales, como imágenes o documentos PDF. Aprenderás a descargar archivos grandes eficientemente y a subir contenido multimedia utilizando peticiones multiparte.
Este capítulo aborda la manipulación de flujos de datos no textuales a través del protocolo HTTP con la biblioteca requests. Aprenderás a utilizar la propiedad .content para extraer bytes puros de forma exacta, evitando la corrupción de archivos provocada por la decodificación automática de texto. Asimismo, se detallan los mecanismos prácticos para persistir de forma segura imágenes y documentos en el almacenamiento local del sistema. Finalmente, dominarás el envío de recursos hacia servidores remotos mediante la codificación multipart/form-data, profundizando tanto en la personalización de metadatos mediante tuplas como en la carga eficiente de múltiples archivos en una sola petición.
7.1. Acceso al contenido binario
Cuando realizas una petición HTTP utilizando la biblioteca requests, el servidor devuelve una respuesta que puede ser puramente de texto (como HTML o JSON) o de naturaleza binaria (como una imagen, un archivo PDF, un archivo comprimido o un ejecutable).
En las secciones anteriores se ha utilizado la propiedad .text del objeto Response para acceder al cuerpo de la respuesta. Sin embargo, .text está diseñada exclusivamente para cadenas de caracteres (strings). Cuando accedes a .text, requests intenta adivinar la codificación de caracteres del servidor (como UTF-8 o ISO-8859-1) y decodifica los bytes automáticamente. Si intentas aplicar este proceso a un archivo binario, la decodificación fallará, corromperá los datos o generará caracteres ilegibles, haciendo que el archivo quede completamente inservible.
Para interactuar con archivos y flujos de datos no textuales de manera exacta, se debe utilizar la propiedad .content.
La propiedad .content
La propiedad .content devuelve el cuerpo de la respuesta HTTP en forma de bytes puros, representados en Python por el tipo de dato bytes. Al usar .content, la biblioteca no realiza ningún tipo de decodificación de texto ni asume ninguna estructura de caracteres; simplemente te entrega la secuencia exacta de ceros y unos que envió el servidor web.
El siguiente diagrama en texto plano ilustra cómo se bifurca el flujo de datos dentro del objeto Response según la propiedad que decidas invocar en tu código:
TEXT
Ejemplo de uso práctico
Para ver la diferencia en el entorno de ejecución, analizaremos qué ocurre cuando solicitamos un recurso binario pequeño, como el icono de una página web (favicon), y cómo se almacena en memoria:
Python
Al ejecutar este script, la salida en la consola se estructurará de la siguiente manera:
TEXT
Como se puede observar, respuesta.content antepone una b al literal de la cadena, indicando que se trata de un objeto de tipo bytes. Cada elemento como \x00 o \x01 representa un valor hexadecimal correspondiente a la estructura exacta del formato de archivo que el servidor ha transmitido.
Consideraciones de memoria con .content
Es fundamental tener en cuenta que la propiedad .content descarga la totalidad del cuerpo de la respuesta directamente en la memoria RAM de tu equipo de forma síncrona.
- Cuándo es seguro usarlo: Con recursos de tamaño reducido o moderado (imágenes de perfil, documentos de texto, archivos de configuración, archivos binarios de pocos megabytes).
- Cuándo se debe evitar: Con archivos que superen la capacidad de memoria disponible o que comprometan la eficiencia del sistema (videos en alta definición, bases de datos masivas o archivos comprimidos de gran volumen). Para estos escenarios de gran envergadura, se emplean técnicas de transmisión por fragmentos que se detallarán más adelante en el ecosistema de la biblioteca.
7.2. Descarga de imágenes y documentos
Una vez comprendido que el acceso al contenido binario debe realizarse exclusivamente mediante la propiedad .content, el siguiente paso fundamental es persistir esos bytes en el almacenamiento local del sistema. Esta técnica permite la descarga directa de recursos multimedia (como archivos PNG, JPG o GIF) y documentos de oficina o maquetación (como PDFs, archivos de Word o Excel) a través de los mecanismos nativos de manejo de archivos de Python combinados con requests.
El patrón de persistencia con open()
Para guardar cualquier recurso binario descargado de la red, es mandatorio abrir el archivo local utilizando el modo de escritura binaria ("wb"). Si omitieras la b y usaras el modo de texto tradicional ("w"), Python intentaría codificar los bytes utilizando el mapa de caracteres local del sistema operativo, corrompiendo la cabecera y la estructura interna del archivo de destino.
El flujo básico para realizar una descarga directa consta de tres pasos secuenciales:
TEXT
A continuación, se presenta un bloque de código funcional que ilustra cómo automatizar la descarga segura de una imagen corporativa y un documento normativo en formato PDF de manera simultánea:
Python
Extracción dinámica del nombre del archivo
En entornos de producción o scripts de raspado web (web scraping), no se suelen asignar nombres estáticos a los archivos descargados. Lo idóneo es heredar el nombre original que el archivo posee en el servidor remoto. Esto se puede lograr de dos formas complementarias:
- A través de la estructura de la URL: Inspeccionando el último segmento de la ruta utilizando el módulo estándar
urllib.parse. - A través de las cabeceras de la respuesta: Leyendo el campo
Content-Dispositionprovisto por el servidor, el cual especifica de forma explícita el nombre que se le debe dar al archivo de manera oficial.
Aquí se demuestra cómo implementar la estrategia basada en la URL utilizando urllib.parse.urlparse combinado con os.path.basename:
Python
Validación previa mediante Content-Type
Antes de proceder a la escritura de archivos binarios, es una buena práctica de ingeniería de software validar que el servidor web esté respondiendo con el tipo MIME esperado. Esto previene que termines guardando una página de error HTML (con un código de estado engañoso) con la extensión de una imagen o de un PDF.
La verificación se realiza consultando la cabecera Content-Type:
Python
7.3. Subida de archivos (Multipart Encoding)
El envío de archivos binarios desde el cliente hacia un servidor web se gestiona habitualmente mediante peticiones HTTP POST (o PUT) utilizando una codificación específica denominada multipart/form-data. Esta codificación divide el cuerpo de la petición en diferentes secciones separadas por un límite único (boundary), permitiendo empaquetar tanto metadatos textuales (como campos de un formulario) como flujos de bytes binarios en una única transacción de red.
La biblioteca requests automatiza por completo este proceso complejo a través del parámetro files.
El parámetro files
Para enviar un archivo, no es necesario que codifiques manualmente los bytes ni que configures las cabeceras Content-Type de la petición. Simplemente debes abrir el archivo local en modo de lectura binaria ("rb") y pasarlo al parámetro files dentro de la función de petición.
El siguiente diagrama en texto plano muestra cómo requests empaqueta un archivo y un campo de texto en una estructura multipart antes de transmitirla por la red:
TEXT
Implementación básica de subida de archivos
A continuación, se detalla el método estándar para realizar la subida de un único documento adjunto:
Python
Regla de oro sobre la gestión de recursos: Siempre debes abrir los archivos utilizando un gestor de contexto (
with). Esto garantiza que el puntero del archivo se cierre correctamente una vez querequestsfinalice la lectura de los bytes y complete la transmisión HTTP, evitando fugas de descriptores en el sistema operativo.
Personalización avanzada del envío Multipart
El parámetro files acepta un diccionario flexible donde el valor asociado a la clave no tiene que ser estrictamente el puntero del archivo abierto. Puedes pasar una tupla que te permite definir explícitamente tres parámetros adicionales: el nombre del archivo en el destino, el tipo de contenido (MIME type) y cabeceras adicionales personalizadas.
La estructura de la tupla sigue este patrón:
Python
Veamos un ejemplo avanzado en el que se sube un archivo asignándole un nombre alternativo, forzando un Content-Type específico, y adjuntando de forma simultánea campos tradicionales de texto utilizando el parámetro data:
Python
Envío de datos binarios en memoria sin archivos físicos
Existen ocasiones en las que generas el contenido binario directamente en tu código de Python (por ejemplo, exportando un gráfico o manipulando bytes en memoria) y necesitas subirlo sin escribir un archivo temporal en el disco duro.
Para lograr esto de forma óptima, puedes simular la estructura de un archivo utilizando cadenas de bytes en memoria combinadas con la tupla explícita:
Python
7.4. Envío de múltiples archivos simultáneos
En el desarrollo de aplicaciones que interactúan con servicios de almacenamiento en la nube, sistemas de gestión documental o plataformas multimedia, surge la necesidad recurrente de cargar más de un elemento dentro de la misma operación atómica de red. La biblioteca requests gestiona el envío concurrente de múltiples archivos extendiendo de forma orgánica la sintaxis del parámetro files.
Existen dos estrategias técnicas para empaquetar múltiples recursos en una única petición de codificación multipart (multipart/form-data): el uso de claves distintas para cada archivo o el agrupamiento de varios archivos bajo una misma clave identificadora utilizando listas.
Estrategia A: Envío de múltiples archivos bajo claves distintas
Esta estructura se aplica cuando el servidor web espera recibir archivos de naturalezas o propósitos diferentes dentro de parámetros nominales específicos de su API (por ejemplo, cargar un avatar de usuario y un documento de identidad por separado).
Para instrumentar este comportamiento, basta con poblar el diccionario de files mapeando cada parámetro del formulario con su respectivo puntero binario de archivo:
Python
Estrategia B: Envío de múltiples archivos bajo una misma clave (Estructura de Lista)
Esta variante se utiliza cuando la API del servidor está diseñada para aceptar una colección o matriz dinámica de elementos indexados bajo un mismo campo común (por ejemplo, una galería de fotos de un producto o un lote adjunto de facturas).
Dado que un diccionario de Python clásico no puede contener claves duplicadas, si intentas definir un diccionario como {"archivos": f1, "archivos": f2}, la última declaración sobrescribirá por completo a la primera. Para solucionar esta restricción, requests te permite pasar una lista de tuplas de dos o tres elementos en lugar de un diccionario tradicional.
El siguiente diagrama en texto plano muestra cómo la lista de tuplas se mapea hacia una estructura repetitiva en la carga útil de la petición HTTP:
TEXT
A continuación se detalla la implementación práctica para cargar de forma masiva un lote de archivos utilizando esta estructura:
Python
Resumen del capítulo
En este Capítulo 7: Respuestas Binarias y Archivos, hemos explorado en profundidad las capacidades de la biblioteca requests para gestionar flujos de información no textuales dentro del protocolo HTTP, abarcando tanto los mecanismos de entrada como los de salida de datos:
- Consumo de datos binarios: Aprendimos que la propiedad
.textcorrompe los archivos no textuales debido a su decodificación automática de caracteres. En su lugar, establecimos el uso de.contentcomo el estándar para extraer la secuencia exacta de bytes (bytes) enviados por el servidor, idóneo para imágenes, PDFs y otros formatos nativos. - Persistencia local: Analizamos el patrón de descarga utilizando las herramientas nativas de Python, enfatizando la importancia de interactuar con el sistema de archivos local en modo de escritura binaria (
"wb") para salvaguardar la integridad de los recursos descargados. - TransmisiónMultipart: Estudiamos el funcionamiento del parámetro
filespara realizar cargas de archivos mediantemultipart/form-data. Descubrimos cómo enviar datos directamente desde la memoria RAM (sin escribir archivos intermedios en disco) y cómo personalizar metadatos críticos como el nombre del archivo y el tipo MIME mediante tuplas explícitas. - Carga simultánea: Finalmente, resolvimos escenarios de cargas complejas mediante el envío de múltiples archivos en una sola petición web, diferenciando entre esquemas con nombres de campos específicos y cargas masivas por lotes bajo un mismo identificador común mediante listas de tuplas.
© 2026 Esdocu. Contenido bajo licencia MIT.
Editar esta página