我需要进行API调用以上传文件以及带有该文件详细信息的JSON字符串。
我正在尝试使用python请求lib来执行此操作:
import requests
info = {
'var1' : 'this',
'var2' : 'that',
}
data = json.dumps({
'token' : auth_token,
'info' : info,
})
headers = {'Content-type': 'multipart/form-data'}
files = {'document': open('file_name.pdf', 'rb')}
r = requests.post(url, files=files, data=data, headers=headers)
这会引发以下错误:
raise ValueError("Data must not be a string.")
ValueError: Data must not be a string
如果我删除了'文件'从请求,它的工作原理 如果我删除了'数据'从请求,它的工作原理 如果我不将数据编码为JSON,它就可以工作。
出于这个原因,我认为错误与在同一请求中发送JSON数据和文件有关。
有关如何使其发挥作用的任何想法?
答案 0 :(得分:18)
不要使用json进行编码。
import requests
info = {
'var1' : 'this',
'var2' : 'that',
}
data = {
'token' : auth_token,
'info' : info,
}
headers = {'Content-type': 'multipart/form-data'}
files = {'document': open('file_name.pdf', 'rb')}
r = requests.post(url, files=files, data=data, headers=headers)
请注意,这可能不一定是您想要的,因为它将成为另一个表单数据部分。
答案 1 :(得分:11)
请参阅此帖子How to send JSON as part of multipart POST-request
不要自行设置Content-type标头,将其留给pyrequests生成
def send_request():
payload = {"param_1": "value_1", "param_2": "value_2"}
files = {
'json': (None, json.dumps(payload), 'application/json'),
'file': (os.path.basename(file), open(file, 'rb'), 'application/octet-stream')
}
r = requests.post(url, files=files)
print(r.content)
答案 2 :(得分:2)
我认为您不能在多部分编码文件中发送数据和文件,因此您还需要将数据设为“文件”:
files = {
'data' : data,
'document': open('file_name.pdf', 'rb')
}
r = requests.post(url, files=files, headers=headers)
答案 3 :(得分:0)
更重要的是:
files = {
'document': open('file_name.pdf', 'rb')
}
只有当您的文件位于脚本所在的目录时才会有效。
如果你想从不同的目录追加文件,你应该这样做:
files = {
'document': open(os.path.join(dir_path, 'file_name.pdf'), 'rb')
}
dir_path 是'file_name.pdf'文件的目录。
但是如果你想发送多个PDF怎么办?
您只需创建一个自定义函数即可返回所需文件列表(在您的情况下,只能使用 .pdf 扩展名)。这还包括子目录中的文件(递归搜索文件):
def prepare_pdfs():
return sorted([os.path.join(root, filename) for root, dirnames, filenames in os.walk(dir_path) for filename in filenames if filename.endswith('.pdf')])
然后你可以打电话给它:
my_data = prepare_pdfs()
用简单的循环:
for file in my_data:
pdf = open(file, 'rb')
files = {
'document': pdf
}
r = requests.post(url, files=files, ...)
答案 4 :(得分:0)
为了发送Facebook Messenger API,我将所有有效负载字典值更改为字符串。然后,我可以将有效负载作为data
参数传递。
import requests
ACCESS_TOKEN = ''
url = 'https://graph.facebook.com/v2.6/me/messages'
payload = {
'access_token' : ACCESS_TOKEN,
'messaging_type' : "UPDATE",
'recipient' : '{"id":"1111111111111"}',
'message' : '{"attachment":{"type":"image", "payload":{"is_reusable":true}}}',
}
files = {'filedata': (file, open(file, 'rb'), 'image/png')}
r = requests.post(url, files=files, data=payload)
答案 5 :(得分:0)
我一直在使用my @vulnerabilities = ($g ~~ m:g/\s+("Low"||"Medium"||"High")\s+/);
对我来说,以下代码有效。
requests==2.22.0