Страницы

Поиск по вопросам

вторник, 21 мая 2019 г.

Как отправить полученный файл на другой сервер?

Есть следующая система.
Существует сервер обработки фото на одном сервере и есть основной сервер.
Пользователь отправляет форму, в которой есть фото, на сервер обработки фото, сервер фото обрабатывает его и отправляет на основной сервер через requests.post. На данный момент работает, только если сначала сохранить файл на физический диск, а потом уже отправить его с (указанием пути) на основной сервер.
Как можно отправить файл через requests.post, не сохраняя его на диск?
Пробовал конвертировать с помощью StringIO, BytesIO, но так ничего и не вышло.
сохраняю на данный момент так:
# Получаю и сохраняю фото f = request.FILES['photo'] f.save(file_path)
# Меняю размер фото image = Image.open(file_path) image.thumbnail([150, 150], Image.ANTIALIAS) image.save(file_path, image.format, quality=100, optimize=1)
# Отправляю так fil = open(file_path, 'rb') filess = {'photo': ('photo.jpg', fil, 'image/jpeg')} request = requests.post("%s%s" % (domen, url), data=post, files=filess)
Собственно нужно отправить уже измененный файл image
На счет вывода тут ошибок не уверен что получится, пробовал разные варианты и много и ошибки в некоторых случаях не выходили, но на основном сервере файл не сохранялся, значит что то не то отправлял, на основном сервере нет возможности посмотреть логи ошибок.
То что я находил по отправке файла через StringIO ничего не работало, то сам модуль ругался что данные не те, то модель по отправке ругался что данные не те, поэтому причина видимо в том что я файл не правильно преобразовывал в StringIO. Видимо мой вопрос сводится к тому как правильно преобразовать этот файл к такому формату и потом как эти данные отправить через requests.post


Ответ

Основной сервер-то как принимает картинку? Тоже как загружаемый файл? Тогда предельно просто:
def upload_view(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): f = request.FILES['photo'] requests.post('http://example.com', files={f.name: f}) return redirect('upload:success') else: form = UploadFileForm() return render(request, 'upload.html', {'form': form})
Если он ожидает поток байт в теле запроса, то чуть сложнее:
def upload_bridge(f): for chunk in f.chunks(): yield chunk
def upload_view(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): requests.post('http://example.com', data=upload_bridge(request.FILES['photo'])) return redirect('upload:success') else: form = UploadFileForm() return render(request, 'upload.html', {'form': form})
Только учтите, что большой файл может надолго поставить обработчик колом. Это может привести либо к обрыву соединения по таймауту, либо исчерпанию обработчиков и последующей недоступности сайта.
UPDATE:
from StringIO import StringIO
f = request.FILES['photo']
input = StringIO(f.read()) output = StringIO()
image = Image.open(input) image.thumbnail([150, 150], Image.ANTIALIAS) image.save(output, 'PNG')
requests.post('http://example.com', files={f.name: output})
output.close() input.close()
Этот вариант не только будет обработчик ставить колом, но ещё и память жрать будет.

Комментариев нет:

Отправить комментарий