1

With server.py running:

from flask import Flask, request, Response

app = Flask(__name__)

@app.route('/test', methods=['GET','POST'])
def route():   
    print('got files: %s' % request.files)
    return Response()

if __name__ == '__main__':
    app.run('0.0.0.0', 5000)

send a request using client.py:

import json, requests  

dictionary_1 = {"file": {"url": "https://bootstrap.pypa.io/get-pip.py"}}  

files = [('dictionary_1', ('get-pip.py', json.dumps(dictionary_1), 'application/json'))]

response = requests.post('http://127.0.0.1:5000/test', files=files)

Server logs that it received a request:

got files: ImmutableMultiDict([('dictionary_1', <FileStorage: u'get-pip.py' ('application/json')>)]) 

Apparently, the dictionary_1 was received as FileStorage object. How to turn the received FileStorage into the Python dictionary?

edited later

The possible duplicate post does not clarify how to send and unpack the Python dictionary object sent via requests(files=list())

alphanumeric
  • 17,967
  • 64
  • 244
  • 392
  • The post you've mentioned does not clarify how to send and unpack the dictionary object using Flask.request.files attribute. – alphanumeric Nov 14 '18 at 22:08

2 Answers2

1

This is happening because you're posting files instead of data. This should work:

import flask

app = flask.Flask(__name__)

@app.route('/test', methods=['GET','POST'])
def route():   
    print('got data: {}'.format(flask.request.json))
    return Response()

if __name__ == '__main__':
    app.run('0.0.0.0', 5000)

and then send data to your app by

import requests  

dictionary_1 = {"file": {"url": "https://bootstrap.pypa.io/get-pip.py"}}  

response = requests.post('http://127.0.0.1:5000/test', json=dictionary_1)

In your example there's no need to post the file unless I'm misunderstanding something

n8sty
  • 1,418
  • 1
  • 14
  • 26
  • I am intentionally using the `requests.post(url, files=list())` and not `requests.post(url, json=str())` since I would like to be able to send both the files and dictionary with the same request. – alphanumeric Nov 14 '18 at 21:58
  • @alphanumeric Your request doesn't include any files. The variable `multiple_files` in the client contains only dicts, lists, and strings. – André C. Andersen Nov 14 '18 at 22:03
  • Since I would like to keep the question as simple as possible the `multiple_files` list contains the dictionary object only and not the files. – alphanumeric Nov 14 '18 at 22:03
1

Solution # 1:

from flask import Flask, request, Response
import StringIO, json 

app = Flask(__name__)

@app.route('/test', methods=['GET','POST'])
def route():  
    print('got files: %s' % request.files)
    for key, file_storage in request.files.items():
        string_io = StringIO.StringIO()
        file_storage.save(string_io)
        data = json.loads(string_io.getvalue())
        print('data: %s type: %s' % (data, type(data)) ) 

    return Response()

if __name__ == '__main__':
    app.run('0.0.0.0', 5000)

Solution # 2:

from flask import Flask, request, Response
import tempfile, json, os, time   

app = Flask(__name__)

@app.route('/test', methods=['GET','POST'])
def route():   
    print('got files: %s' % request.files)

    for key, _file in request.files.items():
        tmp_filepath = os.path.join(tempfile.mktemp(), str(time.time()))
        if not os.path.exists(os.path.dirname(tmp_filepath)):
            os.makedirs(os.path.dirname(tmp_filepath))

        _file.save(tmp_filepath)

        with open(tmp_filepath) as f:
            json_data = json.loads(f.read())

        print type(json_data), json_data 

    return Response(json_data)

if __name__ == '__main__':
    app.run('0.0.0.0', 5000)
alphanumeric
  • 17,967
  • 64
  • 244
  • 392