проблема с aiohttp POST для загрузки бинарного файла

Я успешно использовал модуль requests для загрузки двоичного файла (jpg) с чем-то как следующее:

upload_url = 'http:10.1.1.1:8080/api/media/photo'
headers = {'Authorization': token_string, 'Content-Type': 'image/jpg'}
data = open('photo.JPG', 'rb')
params = {'name': 'photo.JPG'}
r = requests.post(upload_url, params=params, data=data, headers=headers)

Теперь пытаемся сделать это с помощью клиента http://aiohttp.readthedocs.org/en/latest/client.html. Это то, что у меня есть до сих пор:

def upload_photos(token):
    upload_url = '10.0.1.1:8080/api/media/photo'
    headers = {'Authorization': token, 'Content-Type': 'image/jpg'}
    data = {'file': open('photo.JPG', 'rb')}
    params = {'name': 'photo.JPG'}
    r = yield from aiohttp.request('post', upload_url, params=params, data=data, headers=headers)

if __name__ == '__main__':     
    asyncio.get_event_loop().run_until_complete(upload_photos(token))

Но мне возвращают 400 с {"detail": "Specified value is invalid: Invalid Content-Length specified"}.
Как будто неправильно отправляет фото.jpg. В документах aiohttp упоминаются файлы с кодировкой из нескольких частей и потоковая передача, но это не то, чего я хочу здесь.

Как мне сформировать аналогичный POST с двоичным файлом, как в запросах, но с aiohttp?


person Gandalf44    schedule 02.04.2015    source источник


Ответы (1)


Спасибо за сообщение об ошибке. В качестве обходного пути я предполагаю использовать фрагментированное кодирование передачи:

headers['Transfer-Encoding'] = 'chunked'
r = yield from aiohttp.request('post', upload_url, params=params, data=data, headers=headers, chunked=1024) 

Рецепт должен работать, по крайней мере, у нас есть очень похожий код в нашем наборе тестов: https://github.com/KeepSafe/aiohttp/blob/master/tests/test_client_functional.py#L322

Я постараюсь исправить вычисление Content-Length для вашего способа загрузки в следующем выпуске aiohttp.

person Andrew Svetlov    schedule 02.04.2015
comment
Вау, спасибо @Andrew. Последнее, о чем я мог подумать, это то, что я увидел ошибку aiohttp... Я всегда сначала виню себя за то, что не знаю, что делаю ;-). - person Gandalf44; 02.04.2015
comment
Все еще не могу это сделать... вот мой фрагмент кода... я делаю что-то еще не так? headers = {'Authorization': token_string, 'Content-Type': 'image/jpg', 'Transfer-Encoding': 'chunked'} params = {'name': 'photo.JPG'} with open('photo.JPG', 'rb') as f: r2 = yield from aiohttp.request('post', upload_url, params=params, data=f, chunked=1024, headers=headers) - person Gandalf44; 03.04.2015
comment
Я предполагаю, что нужно отправить содержимое файла, а не файловый объект. Что-то вроде data=f.read(). - person Andrew Svetlov; 03.04.2015