【问题标题】:Getting bad request error when posting file to server using python requests library使用python请求库将文件发布到服务器时出现错误的请求错误
【发布时间】:2019-07-06 07:26:22
【问题描述】:

当我尝试使用 python 请求库将文件发布到服务器时,我收到 http 代码 400(错误请求)。

对应curl请求成功:

curl -X POST -i https://de.api.labs.sophos.com/analysis/file/static/v1 \
-H 'Authorization: auth_string' \
-H 'Content-Type: multipart/form-data' \
-F "file=@filename"

API 文档:https://api.labs.sophos.com/doc/analysis/file/static.html

有人可以帮我解决我可能做错了什么吗?
到目前为止我的代码:

import requests

url = "https://de.api.labs.sophos.com/analysis/file/static/v1"
headers = {'content-type': 'multipart/form-data', 'Authorization': authorization}

with open(filepath, 'rb') as f:      
    files = {'file': f}  # Even tried {'file': f.read()}
    r = requests.post(url, files=files, headers=headers)
    if r.status_code in [200, 202]:
        return r.json()
    else:
        return r

【问题讨论】:

    标签: python python-3.x python-requests


    【解决方案1】:

    TL;DR

    尝试这样做:

    import requests
    
    url = "https://de.api.labs.sophos.com/analysis/file/static/v1"
    headers = {'Authorization': authorization}  # no Content-Type here
    
    r = requests.post(url, headers=headers, files={"file": open(filepath, "rb")})
    print(r.status_code, r.text)
    

    为什么

    当posting files 和requests 时,您不应该手动设置Content-Type 标头。

    有两个原因:

    • requests 将在发出实际 HTTP 请求之前将 Content-Type 隐式设置为 multipart/form-data(例如 Content-Length)
    • 使用Content-Type: multipart/form-data 时,您还应该指定boundary。如果没有设置边界,服务器将无法正确读取请求体中的数据。所以边界是Content-Type 标头的必需部分,如果您使用multipart/form-data。

    在您的示例中,您没有为请求设置边界。事实是 requests 不会为您设置它 如果您覆盖 Content-Type 标头(您这样做)。然后服务器无法在请求正文中读取您的文件。因此,它会返回您400 Bad Request。

    您可以在提出请求后输入print(r.request.headers["Content-Type"]) 进行检查。它会输出这个:

    multipart/form-data
    

    ,但它必须看起来像这样:

    multipart/form-data; boundary=6387a52fb4d1465310a2b63b2d1c6e70
    

    另一方面,curl 隐式添加边界,所以你一切都很好,你会收到200 OK。

    你也可以检查一下:

    curl -H 'Content-Type: multipart/form-data' -F "file=@123.txt" -v http://httpbin.org/post
    

    哪些输出:

    * Connected to httpbin.org (34.230.136.58) port 80 (#0)
    > POST /post HTTP/1.1
    > Host: httpbin.org
    > User-Agent: curl/7.47.0
    > Content-Type: multipart/form-data; boundary=------------------------d257f5f4377a3997
    ...
    

    【讨论】:

    • 哇!它在没有内容类型的情况下工作。谢谢伊万,这么详细的回答:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 2020-06-30
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    相关资源
    最近更新 更多