Для понимания этого материала необходимо ознакомиться с передачей дополнительных параметров в запросе методом 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
, и если это произойдет, то это значение будет установлено на количество байтов в файле. При открытии файла в текстовом режиме могут возникнуть ошибки.