Django - опубликовать InMemoryUploadedFile на внешний REST API
В Django Rest Framework я хотел бы опубликовать файл, полученный как InMemoryUploadedFile
на другой сервер, как только он будет получен.
Звучит просто, но request.post()
Похоже, функция не передает должным образом такой файл:
def post(self, request, *args, **kwargs):
data = request.data
print(data)
# <QueryDict: {'file': [<InMemoryUploadedFile: myfile.pdf (application/pdf)>]}>
endpoint = OTHER_API_URL + "/endpoint"
r = requests.post(endpoint, files=data)
Мой другой сервер получает запрос (через колбу) с именем файла, но не с содержимым:
@app.route("/endpoint", methods=["POST"])
def endpoint():
if flask.request.method == "POST":
# I removed the many checks to simplify the code
file = flask.request.files['file']
path = os.path.join(UPLOAD_FOLDER, file.filename)
file.save(path)
print(file) #<FileStorage: u'file.pdf' (None)>
print(os.path.getsize(path)) #0
return [{"response":"ok"}]
При публикации файла непосредственно в этот API в форме данных с почтальоном, он работает как положено:
print(file) # <FileStorage: u'file.pdf' ('application/pdf')>
print(os.path.getsize(path)) #8541
Любая помощь о том, как это исправить, то есть преобразовать InMemoryUploadedFile
типа что-то нормальное REST API может понять? Или, может быть, просто добавление правильных заголовков?
0 ответов
Мне пришлось выяснить эту проблему, передав загруженный файл с внешнего сайта Django в бэкэнд-API Django в Python 3. К фактическим данным файла InMemoryUploadedFile можно получить доступ через метод.getvalue() свойства объекта.file.
path="path/to/api"
in_memory_uploaded_file = request.FILES['my_file']
io_file = in_memory_uploaded_file.file
file_value = io_file.getvalue()
files = {'my_file': file_value}
make_http_request(path, files=files)
и может быть сокращено
file = request.FILES['my_file'].file.getvalue()
files = {'my_file': file}
До этого попытки отправки объектов InMemoryUploadFile, свойства файла или результата метода read() - все это доказывало отправку пустого / пустого файла к тому времени, когда он попал в API.
У меня была такая же проблема и такой же случай. Мое рабочее решение
headers = {
"Host": API_HOST,
"cache-control": "no-cache",
}
try:
data = json_request = request.POST['json_request'].strip()
data = json.loads(data) # important!
except:
raise Http404
try:
in_memory_uploaded_file = request.FILES['file'].file.getvalue()
files = {'photo': in_memory_uploaded_file} # important!
except:
files = {}
if USE_HTTPS:
API_HOST = f'https://{API_HOST}'
else:
API_HOST = f'http://{API_HOST}'
if authorization_key and len(authorization_key) > 0:
response = requests.post(f'{API_HOST}/api/json/?authorization_key={authorization_key}', headers=headers, data=data, files=files)
else:
response = requests.post(f'{API_HOST}/api/json/', headers=headers, data=data)
json_response = json.dumps(response.json())