我有这个问题,我试图在一个函数中向一个烧瓶API发送/接收一些文件和JSON。
在我的客户(发件人)上我有:
#my json to be sent
datas = {'var1' : 'var1','var2' : 'var2',}
#my file to be sent
local_file_to_send = 'user_picture.jpg'
url = "http://10.100.2.6:80/customerupdate"
headers = {'Content-type': 'multipart/form-data'}
files = {'document': open(local_file_to_send, 'rb')}
r = requests.post(url, files=files, data=datas, headers=headers)
在我的Flask服务器上,我有:
class OPERATIONS(Resource):
@app.route('/',methods=['GET'])
def hello_world():
return 'Hello World!'
@app.route('/customerupdate',methods=['GET','POST'])
def customerupdate():
event_data_2 = json.loads(request.get_data().decode('utf-8'))
print event_data_2
我有这条错误消息告诉我数据实际上不是json格式,也不是utf8格式。如果我打印“get_data”的内容而不尝试解码它会显示一些二进制字符..
我的客户端上读取json并在本地写入文件的语法是什么?
答案 0 :(得分:3)
我建议将JSON和文件作为multipart表单的一部分发送。在这种情况下,您将从服务器上的request.files
读取它们。 (一个警告:我使用Python 3测试了所有示例,请求2.18.4和Flask 0.12.2 - 您可能需要更改代码以匹配您的环境。)
从https://stackoverflow.com/a/35940980/2415176(以及http://docs.python-requests.org/en/latest/user/advanced/#post-multiple-multipart-encoded-files处的Flask文档),您无需指定标题或任何内容。您可以让requests
为您处理:
import json
import requests
# Ton to be sent
datas = {'var1' : 'var1','var2' : 'var2',}
#my file to be sent
local_file_to_send = 'tmpfile.txt'
with open(local_file_to_send, 'w') as f:
f.write('I am a file\n')
url = "http://127.0.0.1:3000/customerupdate"
files = [
('document', (local_file_to_send, open(local_file_to_send, 'rb'), 'application/octet')),
('datas', ('datas', json.dumps(datas), 'application/json')),
]
r = requests.post(url, files=files)
print(str(r.content, 'utf-8'))
然后在服务器上,您可以阅读request.files
(请参阅http://flask.pocoo.org/docs/0.12/api/#flask.Request.files,但请注意,request.files的工作方式略有不同,请参阅https://stackoverflow.com/a/11817318/2415176):
import json
from flask import Flask, request
app = Flask(__name__)
@app.route('/',methods=['GET'])
def hello_world():
return 'Hello World!'
@app.route('/customerupdate',methods=['GET','POST'])
def customerupdate():
posted_file = str(request.files['document'].read(), 'utf-8')
posted_data = json.load(request.files['datas'])
print(posted_file)
print(posted_data)
return '{}\n{}\n'.format(posted_file, posted_data)
答案 1 :(得分:3)
感谢Craig的回答,我找到了解决方案。我将发布两个代码(客户端和服务器)以帮助以备将来使用。 CLient服务器正在以"形式上传文件和Json。烧瓶的特点。然后一些和一些dict使Payload更清晰(我知道这是丑陋的方式,但这是最好的学者方法)
在 客户端 方面:
datas = {'CurrentMail': "AA", 'STRUserUUID1': "BB", 'FirstName': "ZZ", 'LastName': "ZZ", 'EE': "RR", 'JobRole': "TT" }
#sending user infos to app server using python "requests"
url = "http://10.100.2.6:80/customerupdate"
def send_request():
payload = datas
local_file_to_send = 'user_picture.jpg'
files = {
'json': (None, json.dumps(payload), 'application/json'),
'file': (os.path.basename(local_file_to_send), open(local_file_to_send, 'rb'), 'application/octet-stream')
}
r = requests.post(url, files=files)
send_request()
在 Flask服务器 方面:
import sys, os, logging, time, datetime, json, uuid, requests, ast
from flask import Flask, request , render_template
from werkzeug import secure_filename
from werkzeug.datastructures import ImmutableMultiDict
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
app.debug = True
class OPERATIONS(Resource):
@app.route('/',methods=['GET'])
def hello_world():
return 'Hello World!'
@app.route('/customerupdate',methods=['GET','POST'])
def customerupdate():
print "************DEBUG 1 ***********"
RequestValues = request.values
print RequestValues
print "************DEBUG 2 ***********"
RequestForm = request.form
print RequestForm
print "************DEBUG 2-1 ***********"
so = RequestForm
json_of_metadatas = so.to_dict(flat=False)
print json_of_metadatas
print "************DEBUG 2-2 ***********"
MetdatasFromJSON = json_of_metadatas['json']
print MetdatasFromJSON
print "************DEBUG 2-3 ***********"
MetdatasFromJSON0 = MetdatasFromJSON[0]
print MetdatasFromJSON0
print "************DEBUG 3-5 ***********"
strMetdatasFromJSON0 = str(MetdatasFromJSON0)
MetdatasDICT = ast.literal_eval(strMetdatasFromJSON0)
print MetdatasDICT
print "************DEBUG 3-5 ***********"
for key in MetdatasDICT :
print "key: %s , value: %s" % (key, MetdatasDICT[key])
print "************DEBUG 4 ***********"
f = request.files['file']
f.save(secure_filename(f.filename))
print "FILE SAVED LOCALY"
return 'JSON of customer posted'
答案 2 :(得分:2)
如果这不在生产中,那么有一种比将json绑定到文件中更简单的方法,将json数据作为参数值发送,而不是将其绑定到json中。
datas = {data: {'var1' : 'var1','var2' : 'var2}}
url = "http://10.100.2.6:80/customerupdate"
files = {'document': open(local_file_to_send, 'rb')}
headers = {'Content-type': 'application/json'}
r = requests.post(url, files=files, params=datas, headers=headers)
并且在flask服务器中,数据和文件的接收方式为:
image = request.files.get('image')
data = request.args.get('data')
答案 3 :(得分:0)
我能够通过 TestClient post 在 data 属性中发送 json 和文件,如下所示:
with self.app.test_client() as c:
data = {'here': 'is', 'some': 'data' }
data={
'file': filename, open(filename, 'rb'), "image/jpeg"),
'json': json.dumps(data)}
rv = c.post(url, data=data)
可以从请求表单加载服务器端json:
json_data = json.loads(request.form["json"])
可以从文件中加载文件
file = request.files["file"]
通过这种方式可以清楚地区分文件和其他数据。
我在此处找到了数据的外观:https://werkzeug.palletsprojects.com/en/1.0.x/test/#werkzeug.test.EnvironBuilder