问题概述:python发送带有文件的post请求时候,没有走提交文件的那一段代码
自己在编写接口自动化框架的时候遇到了一个问题,在处理request请求的时候区分get和post,再根据content-type的不同处理post请求,以下是处理请求的方法
def handle_requests(method, url, params=None, data=None, json_data=None, headers=None, files=None, auth=None):
"""
发送HTTP请求的通用函数
:param method: 请求方法,支持 GET 和 POST
:param url: 请求URL
:param params: 请求URL参数(GET请求的参数)
:param data: POST请求的表单数据
:param json_data: POST请求的JSON数据
:param headers: 请求头部信息
:param auth: HTTP认证信息,如 (username, password)
:return: requests.Response 对象
"""
if method == 'GET':
res = requests.get(url, params=params, headers=headers, auth=auth)
return res
elif method == 'POST':
if 'application/json' == headers['content-type']:
res = requests.post(url, json=json_data, headers=headers)
return res
elif 'application/x-www-form-urlencoded' == headers['content-type']:
encoded_data = '&'.join([f"{key}={value}" for key, value in data.items()])
res = requests.post(url, data=encoded_data, headers=headers)
return res
elif 'multipart/form-data' == headers['content-type']:
if files is not None:
data_with_file = data.copy()
data_with_file.update(files)
multipart_data = MultipartEncoder(fields=data_with_file)
headers['content-type'] = multipart_data.content_type
res = requests.post(url, data=multipart_data, headers=headers)
return res
else:
multipart_data = MultipartEncoder(fields=data)
headers['content-type'] = multipart_data.content_type
res = requests.post(url, data=multipart_data.to_string(), headers=headers)
return res
else:
raise ValueError("only support 'GET' and 'POST'")
if __name__ == '__main__':
method = 'POST'
url = 'http://127.0.0.1:8888/upload'
data = {
'name': "test",
'email': "123",
'message': "123",
}
files = {'file': (open('/Users/***/PycharmProjects/logindemo/1.txt', 'rb'))}
# files = {'file': ('1.txt',open('/Users/***/PycharmProjects/logindemo/1.txt', 'rb'), 'multipart/form-data')}
headers = {'content-type': 'multipart/form-data'}
res = handle_requests(method=method, url=url, data=data, headers=headers, files=files)
print(res.text)
服务端的代码如下:
```python
@app.route('/upload', methods=['POST'])
def upload_something():
if request.method == 'POST':
# pdb.set_trace() # 插入调试语句
file = request.files.get('files')
if file is not None:
return upload_file()
else:
return submit_form()
else:
return error_methods()
def upload_file():
# pdb.set_trace() # 插入调试语句
file = request.files.get("files")
# 如果目录不存在,则创建"uploaded_files"目录
upload_dir = os.path.join(BASE_DIR, 'uploaded_files')
os.makedirs(upload_dir, exist_ok=True)
# 将文件保存到"uploaded_files"目录
file_path = os.path.join(upload_dir, file.filename)
file.save(file_path)
name = request.form.get('name')
email = request.form.get('email')
message = request.form.get('message')
print(f"Name: {name}, Age: {email}, Message:{message}")
return jsonify({'message': 'File uploaded successfully!',
'data': {'name': name, 'email': email, 'message': message + ', File uploaded successfully'}})
def submit_form():
form_data = request.form
print(form_data)
name = form_data.get('name')
email = form_data.get('email')
message = form_data.get('message')
return jsonify(
{'message': 'Form submitted successfully!', 'data': {'name': name, 'email': email, 'message': message}})
个人排查问题:
1.使用postman调用接口的时候正常,并且正常返回{
"data": {
"email": "123",
"message": "qqq, File uploaded successfully",
"name": "1qqq"
},
"message": "File uploaded successfully!"
}
2.使用pdb查看服务端接受到的数据
```python
python发送请求
(Pdb) p request.form
ImmutableMultiDict([('name', 'test'), ('email', '123'), ('message', '123'), ('file', '测试')])
(Pdb) (Pdb) p request.files
ImmutableMultiDict([])
postman发送请求
(Pdb) p request.form
ImmutableMultiDict([('name', '1qqq'), ('email', '123'), ('message', 'qqq')])
(Pdb) p request.files
ImmutableMultiDict([('files', <FileStorage: '1.txt' ('text/plain')>)])
目前判断是post在处理文件的时候有问题,但是找不到原因,希望大家帮忙看看
问题出在您的请求处理函数中,具体原因是在请求头部中使用了不正确的字段名。在发送请求时,您设置了headers = {'content-type': 'multipart/form-data'},但在服务端接收请求时,您使用request.files.get('files')来获取文件数据。
要解决这个问题,您需要将请求头部中的字段名修改为与服务端代码中一致。将headers = {'content-type': 'multipart/form-data'}修改为headers = {'Content-Type': 'multipart/form-data'},注意首字母大写并使用连字符替代下划线。
另外,在服务端代码中,请将file = request.files.get('files')修改为file = request.files.get('file'),以匹配调整后的请求头部字段名。
这样更改后,重新运行您的代码应该能够正确处理带有文件的POST请求。
如果您在使用Python发送带有文件的POST请求时发现没有按预期执行上传文件的代码段,可能有以下几个原因:
1.代码逻辑错误:请确保您的代码正确处理文件上传部分。检查您的代码是否正确指定了文件参数并打开了文件,以及是否将文件参数正确传递给POST请求。
2.文件路径错误:确保您提供了正确的文件路径。在发送POST请求之前,请验证文件的确切路径,并确保文件存在并可读。
3.请求头部缺失:发送文件时,通常需要设置正确的请求头部信息,包括Content-Type等。请确保您的代码设置了正确的请求头部信息以支持文件上传。
4.请求方法错误:确认您使用的是正确的HTTP请求方法。通常,文件上传需要使用POST方法。
以下是一个使用Python requests 库发送带有文件的POST请求的示例代码:
import requests
url = "http://example.com/upload" # 上传文件的目标URL
file_path = "/path/to/file.txt" # 要上传的文件路径
files = {'file': open(file_path, 'rb')} # 打开文件并作为表单数据添加到 'file' 字段
response = requests.post(url, files=files)
print(response.status_code)
print(response.text)
在这个示例中,我们使用了requests库向url发送了一个POST请求,携带了一个名为'file'的文件参数。请将示例中的URL和文件路径替换为您的实际URL和文件路径,然后运行代码以验证文件上传是否正常。