Сообщить об ошибке.

Загрузка файлов на сервер модулем requests в Python.

Для понимания этого материала необходимо ознакомиться с передачей дополнительных параметров в запросе методом POST, который представлен в ознакомительной статье к библиотеке requests.

Отправка одного файла на сервер.

Библиотека requests упрощает загрузку файлов на сервер с многосоставной кодировкой Multipart-encoded. Для этого, в словарь с дополнительными параметрами POST запроса необходимо добавить ключ 'file', а в качестве его значения указать объект открытого файла с помощью функции open() в двоичном режиме 'rb':

Сразу смотрим пример:

>>> import requests
# целевой URL-адрес
>>> url = 'https://httpbin.org/post'
# открываем файл на чтение в 
# бинарном режиме ('rb')
>>> fp = open('report.xls', 'rb')
# помещаем объект файла в словарь 
# в качестве значения с ключом 'file'
>>> files = {'file': fp}
# передаем созданный словарь аргументу `files`
>>> resp = requests.post(url, files=files)
>>> fp.close()
>>> resp.text
# {
#   ...
#   "files": {
#     "file": "<censored...binary...data>"
#   },
#   ...
# }

Можно явно указать имя файла, content_type и другие заголовки в значении ключа file создаваемого словаря, для передачи файла на сервер:

>>> import requests
>>> url = 'https://httpbin.org/post'
>>> fp = open('report.xls', 'rb')
# указываем дополнительные заголовки и параметры
>>> files = {'file': ('report.xls', fp, 'application/vnd.ms-excel', {'Expires': '0'})}
>>> resp = requests.post(url, files=files)
>>> fp.close()
>>> resp.text
# {
#   ...
#   "files": {
#     "file": "<censored...binary...data>"
#   },
#   ...
# }

При желании, вместо самого файла можно отправить строку, представляющую контент файла:

>>> import requests
>>> url = 'https://httpbin.org/post'
>>> files = {'file': ('report.csv', 'some, data, to, send\nanother, row, to, send\n')}
>>> resp = requests.post(url, files=files)
>>> resp.text
# {
#   ...
#   "files": {
#     "file": "some,data,to,send\\nanother,row,to,send\\n"
#   },
#   ...
# }

Отправка нескольких файлов на сервер.

Постоянно возникают ситуации, когда необходимо отправить несколько файлов на сервер в одном запросе. Например, предположим, что надо загрузить файлы изображений в HTML-форму с несколькими полями из файлов изображений .png:

<input type="file" name="images" multiple="true" required="true"/>

Для этого просто передаем файловые объекты (предварительно открытые функцией open() в двоичном режиме 'rb') в список кортежей следующего вида (form_field_name, file_info):

>>> import requests
# целевой адрес с формой отправки
>>> url = 'https://httpbin.org/post'
# добавляем файловые объекты в список кортежей
>>> multiple_files = [
...     ('images', ('foo.png', open('foo.png', 'rb'), 'image/png')),
...     ('images', ('bar.png', open('bar.png', 'rb'), 'image/png'))]
# делаем запрос
>>> resp = requests.post(url, files=multiple_files)
>>> resp.text
{
  ...
  'files': {'images': 'data:image/png;base64,iVBORw ....'}
  'Content-Type': 'multipart/form-data; boundary=31316...',
  ...
}

Предупреждение. Настоятельно рекомендуется открывать файлы в двоичном режиме 'rb'. Это связано с тем, что запросы могут попытаться предоставить заголовок Content-Length, и если это произойдет, то это значение будет установлено на количество байтов в файле. При открытии файла в текстовом режиме могут возникнуть ошибки.