Есть следующая система.
Существует сервер обработки фото на одном сервере и есть основной сервер.
Пользователь отправляет форму, в которой есть фото, на сервер обработки фото, сервер фото обрабатывает его и отправляет на основной сервер через 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()
Этот вариант не только будет обработчик ставить колом, но ещё и память жрать будет.
Комментариев нет:
Отправить комментарий