【发布时间】: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,它应该是string 或byte-type。但在这个 POST 中,它是一个元组。为什么会出现这样的错误?
【问题讨论】:
-
该代码不会导致该错误。您根本不调用 JSON 模块。您是否对由此返回的返回进行 JSON 解码?是否打印了响应代码和文本?
-
你说得对,我还有一行要打印出 JSON 格式的响应。我对我的问题进行了更多编辑。