问题概述:python发送带有文件的post请求时候,没有走提交文件的那一段代码,如何解决?

问题概述: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和文件路径,然后运行代码以验证文件上传是否正常。