【问题标题】:Python requests POST file with multipart form and cookiesPython 请求带有多部分表单和 cookie 的 POST 文件
【发布时间】:2022-01-20 23:16:59
【问题描述】:

我需要使用 cookie 上传包含有关该文件的一些信息的文件。如下命令行可以正常工作:

curl -v -X -POST -F file=@"path_to_file/my_file.xml; type=text/xml" -F rowData='{"fileVersion":"1.0", "owner":"xyz", "fileName":"my_file.xml"}' https://x.x.x.x:xxxx/path_to_receiving_point -H 'Cookie: my_cookie_goes_here'

我想使用 requests 将该命令转换为 Python。

import requests

#First I get the cookies with a POST
#please assume this part works and I get a <RequestsCookieJar> output below
req = requests.POST(...)
cookies = req.cookies

#Then I construct the actual request to upload file
address = "https://x.x.x.x:xxxx/path_to_receiving_point"
rowData = {"fileVersion":"1.0", "owner":"xyz", "fileName":"my_file.xml"}
#files = {'file': ("path_to_file/my_file.xml", open("path_to_file/my_file.xml", 'rb'), 'type=text/xml', rowData)}
files = {'file': ('my_file.xml', open("path_to_file/my_file.xml", 'rb'), 'type=text/xml', rowData)}

upload_req = requests.post(address,  files=files, cookies=cookies)

print(upload_req.json())

这是正确的方法吗?因为我收到这个错误:

raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

对于cookies,它是这样的:

<RequestsCookieJar[<Cookie userData=%7B%22access_token%22%3A%2288fcdfb8-451f-4607-9517-9ecae16c9285%22%2C%22role%22%3A%5B1%2C5%2C32%5D%2C%22authType%22%3A%22LOCAL%22%2C%22user%22%3A%22admin%22%2C%22password_regex%22%3A%22%28%28%3F%3D.*%5BA-Z%5D%29%28%3F%3D.*%5Ba-z%5D%29%28%3F%3D.*%5C%5Cd%29%28%3F%3D.*%5B__special%5D%29.%7B15%2C%7D%29%22%2C%22special_chars%22%3A%22%21%5C%22%23%24%25%26%27%28%29*%2B%2C-.%2F%3A%3B%3C%3D%3E%3F%40%5B%5D%5E_%60+%7B%5C%5C%7C%7D%7E%22%7D for x.x.x.x/path_to_login/login>]>

更新:只是为了确认我能够验证cookies 部分是否正确。我现在怀疑files dict 的格式不正确。如果有人可以就此提出建议?

更新 2:我编辑了 files 字典以排除上面的第一个文件名。现在我得到的错误是:

return request('post', url, data=data, json=json, **kwargs)
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/requests/sessions.py", line 528, in request
    prep = self.prepare_request(req)
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/requests/sessions.py", line 456, in prepare_request
    p.prepare(
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/requests/models.py", line 319, in prepare
    self.prepare_body(data, files, json)
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/requests/models.py", line 512, in prepare_body
    (body, content_type) = self._encode_files(files, data)
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/requests/models.py", line 166, in _encode_files
    rf.make_multipart(content_type=ft)
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/urllib3/fields.py", line 268, in make_multipart
    self._render_parts(
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/urllib3/fields.py", line 226, in _render_parts
    parts.append(self._render_part(name, value))
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/urllib3/fields.py", line 206, in _render_part
    return self.header_formatter(name, value)
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/urllib3/fields.py", line 117, in format_header_param_html5
    value = _replace_multiple(value, _HTML5_REPLACEMENTS)
  File "/home/username/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/urllib3/fields.py", line 90, in _replace_multiple
    result = pattern.sub(replacer, value)
TypeError: expected string or bytes-like object

这个错误似乎是说 XML 文件没有读入 string 或 ```bytes-like```` 对象。

更新 3:

所以我进一步挖掘了这个文件

/home/usernme/.local/share/virtualenvs/proj-zrz-666L/lib/python3.9/site-packages/urllib3/fields.py

特别是功能:

def _replace_multiple(value, needles_and_replacements):
    def replacer(match):
        return needles_and_replacements[match.group(0)]

    pattern = re.compile(
        r"|".join([re.escape(needle) for needle in needles_and_replacements.keys()])
    )
    result = pattern.sub(replacer, value)
    return result

显然,这个函数接受一个参数value,它应该是stringbyte-type。但在这个 POST 中,它是一个元组。为什么会出现这样的错误?

【问题讨论】:

  • 该代码不会导致该错误。您根本不调用 JSON 模块。您是否对由此返回的返回进行 JSON 解码?是否打印了响应代码和文本?
  • 你说得对,我还有一行要打印出 JSON 格式的响应。我对我的问题进行了更多编辑。

标签: python python-requests


【解决方案1】:

只有当您的服务使用一些 JSON 序列化程序序列化数据时,您才能使用 upload_req.json() 反序列化响应。显然,您的回复 Content-type 不是JSON

在直接写print(upload_req.json()) 之前,您可以简单地使用print(upload_req.text) or print(upload_req.__dict__) 检查响应,这样您就可以看到响应中存在的所有内容,包括响应标头,然后您可以正确地对parsing 做出决定。

【讨论】:

  • 谢谢。上述错误发生在请求本身。意思是,请求未完成,因为 stringbytes-like 对象中没有某些内容。我怀疑问题在于如何将整个 XML 文件读入要发布的数据流中。
猜你喜欢
  • 2023-01-23
  • 2014-06-01
  • 2019-02-19
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 2016-06-29
  • 2020-04-25
  • 2016-06-13
相关资源
最近更新 更多