Отправка файлов через requests: методы и примеры

Раздел: Сетевое программирование -> HTTP-запросы

Отправка файла через библиотеку requests

Наиболее эффективный способ передачи файла с помощью библиотеки requests заключается в использовании параметра files в методе post(). Этот способ позволяет корректно сформировать multipart/form-data запрос, автоматически вычисляет заголовок Content-Type и размер файла. Пример:

import requests

url = 'https://httpbin.org/post'
with open('example.txt', 'rb') as f:
    response = requests.post(url, files={'file': f})
print(response.status_code)
print(response.json())

запрос страницы python (запрос веб-страницы в python)

Здесь файл открывается в бинарном режиме, передается в словаре с ключом 'file'. Сервер получает файл с именем 'example.txt'. После завершения запроса контекстный менеджер закрывает файл.

Типичные ошибки:

  • Забыть открыть файл в режиме 'rb' - при текстовом режиме ('r') возможны проблемы с кодировкой.
  • Не указывать имя файла - сервер может не принять данные.
  • Использовать глобальный конструктор open без контекстного менеджера - риск утечки файлового дескриптора.

Как отправить файл с произвольным именем?

Если требуется изменить имя, передаваемое на сервер, можно использовать кортеж (filename, fileobj, content_type):

files = {'file': ('custom_name.txt', open('example.txt', 'rb'), 'text/plain')}
response = requests.post(url, files=files)

Python requests (библиотека requests в python)

Первый элемент кортежа - новое имя, второй - файлоподобный объект, третий - MIME-тип (опционально).

Без указания MIME-типа requests попытается угадать его по расширению. При нестандартных расширениях лучше задавать явно.

Как отправить несколько файлов за один запрос?

В словаре files можно указать несколько ключей или один ключ со списком кортежей:

files = [
    ('file1', ('a.txt', open('a.txt', 'rb'), 'text/plain')),
    ('file2', ('b.txt', open('b.txt', 'rb'), 'text/plain'))
]
response = requests.post(url, files=files)

Http error requests python (обработка http ошибок в requests)

Это удобно для загрузки галереи изображений или пакета документов.

Как передать файл вместе с дополнительными полями формы?

Параметр data объединяется с files в одном POST запросе:

response = requests.post(url, data={'user': 'alice'}, files={'image': open('photo.jpg', 'rb')})

Make request python (выполнение http-запроса)

Сервер получает и обычные поля, и файл.

Как отправить файл без сохранения на диске (из потока)?

Можно передать объект BytesIO:

from io import BytesIO

buffer = BytesIO(b'Some binary content')
response = requests.post(url, files={'file': ('data.bin', buffer, 'application/octet-stream')})

Python urllib3 request (использование urllib3 для запросов)

Имя обязательно, иначе сервер может не распознать вложение.

Проблема: если не указать имя, requests может использовать имя 'unknown' или вовсе не отправить заголовок Content-Disposition, что нарушит стандарт.

Как отправить большой файл частями (chunked transfer encoding)?

Для отправки большого файла без загрузки в память целиком используется параметр data как генератор:

def generate_chunks(file_path, chunk_size=8192):
    with open(file_path, 'rb') as f:
        while chunk := f.read(chunk_size):
            yield chunk

response = requests.post(url, data=generate_chunks('large_file.iso'), headers={'Transfer-Encoding': 'chunked'})

Этот способ не использует files, а передаёт тело запроса напрямую. Подходит для потоковой передачи, но сервер должен поддерживать chunked encoding.

При таком подходе теряется информация об имени файла. Если сервер ожидает multipart/form-data, данный вариант не сработает.

- Python request download (скачивание файла через requests)

Примеры с расширенными подробностями

Пример 1. Отправка файла с указанием MIME-типа

Пример
import requests

url = 'https://httpbin.org/post'
files = {'document': ('report.pdf', open('report.pdf', 'rb'), 'application/pdf')}
response = requests.post(url, files=files)
print('Status:', response.status_code)
print('Response:', response.json())
Status: 200
Response: {'files': {'document': '... binary content ...'}, 'form': {}, ...}

В ответе httpbin.org возвращает переданные файлы в поле 'files'.

Пример 2. Отправка нескольких файлов разных типов

Пример
url = 'https://httpbin.org/post'
with open('image.png', 'rb') as img, open('data.csv', 'rb') as csv:
    files = [
        ('image', ('photo.png', img, 'image/png')),
        ('data', ('stats.csv', csv, 'text/csv'))
    ]
    response = requests.post(url, files=files)
print('Files count:', len(response.json()['files']))
Files count: 2

Каждый файл передан под своим ключом ('image', 'data').

Пример 3. Отправка файла из строки (BytesIO)

Пример
from io import BytesIO
import json

data = json.dumps({'key': 'value'}).encode()
bio = BytesIO(data)
files = {'upload': ('metadata.json', bio, 'application/json')}
response = requests.post('https://httpbin.org/post', files=files)
print('Uploaded file size:', len(response.json()['files']['upload']))
Uploaded file size: 16

Полезно, если данные формируются динамически в памяти.

Пример 4. Отправка файла с сессией (автоматическое сохранение cookies)

Пример
session = requests.Session()
# предположим, что нужно авторизоваться
session.post('https://example.com/login', data={'user': 'admin', 'pass': 'secret'})
# затем загрузить файл
with open('new_data.txt', 'rb') as f:
    response = session.post('https://example.com/upload', files={'file': f})
print(response.status_code)

Сессия сохраняет куки, что позволяет передавать файлы на защищённые ресурсы.

Пример 5. Обработка ошибок при отправке

Пример
import requests
from requests.exceptions import RequestException

try:
    with open('missing.txt', 'rb') as f:
        resp = requests.post('http://httpbin.org/post', files={'file': f}, timeout=5)
    resp.raise_for_status()
except FileNotFoundError:
    print('Файл не найден')
except RequestException as e:
    print('Ошибка запроса:', e)

Код демонстрирует перехват исключений, связанных с отсутствием файла и сетевыми проблемами.

Отправка файла через requests - comments

En
Python request files file name (python)