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())
Другие вопросы по тегам