解析POST请求体中的数据时,使用'request.form'和'request.get_json()'有什么区别?

问题描述 投票:0回答:1

情况描述:

@app.route('/auth/audio/save', methods=['POST'])
def save_audio():
    # files = request.files
    resp_dict = {'message': "success"}
    file = request.files.get("file")
    if file.filename == "":
        resp_dict['message'] = "[No file] file.filename == ''"
        return jsonify(resp_dict), 400
    # data = request.get_json()
    data = request.form
    logger.info(f"data: {data}")
    check_required_params(data, ['user_id'])
    user_id = data["user_id"]
    audio_dir = os.path.join(app_dir, 'db_files/audio')
    save_path = os.path.join(audio_dir, f'{user_id}.bin')
    file.save(save_path)
    return jsonify(resp_dict), 200

我有一个 Flask 视图函数,它处理 POST 请求,该请求发送包装在请求正文中的文件和数据。

发送请求代码如下所示:

def test_send_audio():
    cur_dir = os.path.dirname(os.path.abspath(__file__))
    audiopath = os.path.join(cur_dir, "test.wav")
    files = {'file': open(audiopath, 'rb')}
    data = {"user_id": 2}
    # headers = {
    #     "Content-Type": "multipart/form-data",
    # }
    # NOTE: Not sure why handlers can't get files when I add headers
    response = requests.post(
        save_audio_url,
        # headers=headers,
        files=files,
        data=data,
    )

我的问题:

  1. 在视图函数中,使用'request.form'和'request.get_json()'有什么区别?就我而言,哪一种是最佳实践?另一种的最佳用例是什么?
  2. 为什么添加“Content-Type”:“multipart/form-data”这样的标头会让视图函数在处理请求时无法获取文件,但如果我不添加这个标头它就能工作?
  3. 一般来说,实施我所描述的案例的最佳实践是什么?
http flask python-requests
1个回答
0
投票
  1. request.form
    存储表单数据。
    request.get_json()
    获取请求正文中的 JSON 数据。这两种类型的数据通过其媒体类型来区分。表单数据将为
    multipart/form-data
    application/x-www-form-urlencoded
    application/x-url-encoded
    。 JSON 数据将是
    application/json
    。这里的区别在于
    multipart/form-data
    可以处理文件上传,这就是您在这里所做的,而
    application/json
    则不能。当您发送不涉及文件的结构化数据时,JSON 数据是更好的选择。

  2. 顾名思义,

    multipart
    类型是具有多个部分的数据。不同的部分应该用“边界”分隔,“边界”是分隔这些不同数据块的任意字符串。更好的解释是here。在您的代码中,
    requests
    库将自动生成边界并使用该边界填充请求正文中的数据。因此,您不应在标头中手动指定内容类型。您可以尝试打印
    request.headers
    request.get_data()
    来查看这一点。

  3. 您正在尝试接收文件并使用

    user_id
    作为文件名保存它。我假设
    user_id
    是发送此请求的用户的 ID(如果是这种情况请告诉我)。我们通常不会在请求正文中存储或发送会话信息(在本例中为
    user_id
    ),因为这是一种很差的安全实践。相反,我们将会话信息编码在令牌(通常是 JWT 令牌)中,并将其放入请求标头中。

希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.