Django-将InMemoryUploadedFile发布到外部REST API

时间:2018-07-05 10:52:40

标签: python django django-rest-framework

在Django Rest框架中,我想在收到文件后立即将以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

有关如何解决此问题的任何帮助,即以普通的REST API可以理解的方式转换InMemoryUploadedFile类型吗?还是只是添加正确的标题?

2 个答案:

答案 0 :(得分:2)

我不得不弄清楚这个问题,原因是将上传的文件从Django前端网站传递到Python 3中的Django后端API。InMemoryUploadedFile的实际文件数据可以通过对象的.file属性的.getvalue()方法访问。 / p>

        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之前已发送空白/空文件。

答案 1 :(得分:1)

我有相同的问题和相同的情况。 我的工作解决方案

    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())