如何在python中发送多部分/表单数据请求?怎么发文件,我懂,但是怎么用这种方法发表单数据就不懂了。
当前回答
为了澄清上面的例子,
即使不需要上传任何文件,也需要使用files参数发送多部分表单POST请求。
文件= {}
不幸的是,这行不通。
您将需要放入一些虚拟值,例如。
files={"foo": "bar"}
当我试图上传文件到Bitbucket的REST API时,我遇到了这个问题,不得不写这个讨厌的东西,以避免可怕的“不支持的媒体类型”错误:
url = "https://my-bitbucket.com/rest/api/latest/projects/FOO/repos/bar/browse/foobar.txt"
payload = {'branch': 'master',
'content': 'text that will appear in my file',
'message': 'uploading directly from python'}
files = {"foo": "bar"}
response = requests.put(url, data=payload, files=files)
:O=
其他回答
import json
import os
import requests
from requests_toolbelt import MultipartEncoder
AUTH_API_ENDPOINT = "http://localhost:3095/api/auth/login"
def file_upload(path_img, token ):
url = 'http://localhost:3095/api/shopping/product/image'
name_img = os.path.basename(path_img)
mp_encoder = MultipartEncoder(
fields={
'email': 'mcm9@gmail.com',
'source': 'tmall',
'productId': 'product_0001',
'image': (name_img, open(path_img, 'rb'), 'multipart/form-data')
#'spam': ('spam.txt', open('spam.txt', 'rb'), 'text/plain'),
}
)
head = {'Authorization': 'Bearer {}'.format(token),
'Content-Type': mp_encoder.content_type}
with requests.Session() as s:
result = s.post(url, data=mp_encoder, headers=head)
return result
def do_auth(username, password, url=AUTH_API_ENDPOINT):
data = {
"email": username,
"password": password
}
# sending post request and saving response as response object
r = requests.post(url=url, data=data)
# extracting response text
response_text = r.text
d = json.loads(response_text)
# print(d)
return d
if __name__ == '__main__':
result = do_auth('mcm4@gmail.com','123456')
token = result.get('data').get('payload').get('token')
print(token)
result = file_upload('/home/mcm/Pictures/1234.png',token)
print(result.json())
您需要使用网站HTML中上传文件的name属性。例子:
autocomplete="off" name="image">
你看到name="image">?你可以在上传文件的网站的HTML中找到它。您需要使用它来上传Multipart/form-data文件
脚本:
import requests
site = 'https://prnt.sc/upload.php' # the site where you upload the file
filename = 'image.jpg' # name example
这里,在image的位置,用HTML添加上传文件的名称
up = {'image':(filename, open(filename, 'rb'), "multipart/form-data")}
如果上传需要点击按钮进行上传,可以这样使用:
data = {
"Button" : "Submit",
}
然后启动请求
request = requests.post(site, files=up, data=data)
完成,文件上传成功
下面是使用请求上传带有附加参数的单个文件的简单代码片段:
url = 'https://<file_upload_url>'
fp = '/Users/jainik/Desktop/data.csv'
files = {'file': open(fp, 'rb')}
payload = {'file_id': '1234'}
response = requests.put(url, files=files, data=payload, verify=False)
请注意,您不需要显式地指定任何内容类型。
注:想评论上述答案之一,但不能因为低声誉,所以起草了一个新的回应在这里。
这是在多部分请求中发送文件的一种方法
import requests
headers = {"Authorization": "Bearer <token>"}
myfile = 'file.txt'
myfile2 = {'file': (myfile, open(myfile, 'rb'),'application/octet-stream')}
url = 'https://example.com/path'
r = requests.post(url, files=myfile2, headers=headers,verify=False)
print(r.content)
其他方法
import requests
url = "https://example.com/path"
payload={}
files=[
('file',('file',open('/path/to/file','rb'),'application/octet-stream'))
]
headers = {
'Authorization': 'Bearer <token>'
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
我都测试过了,两者都很好。
即使不需要上传任何文件,也需要使用files参数发送多部分表单POST请求。
从原始请求来源:
def request(method, url, **kwargs):
"""Constructs and sends a :class:`Request <Request>`.
...
:param files: (optional) Dictionary of ``'name': file-like-objects``
(or ``{'name': file-tuple}``) for multipart encoding upload.
``file-tuple`` can be a 2-tuple ``('filename', fileobj)``,
3-tuple ``('filename', fileobj, 'content_type')``
or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``,
where ``'content-type'`` is a string
defining the content type of the given file
and ``custom_headers`` a dict-like object
containing additional headers to add for the file.
file-tuple可以是a:
2元组(文件名,fileobj) 3-tuple (filename, fileobj, content_type) 4元组(文件名,fileobj, content_type, custom_headers)。
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
基于以上,最简单的多部分表单请求,包括要上传的文件和表单字段,将如下所示:
import requests
multipart_form_data = {
'upload': ('custom_file_name.zip', open('myfile.zip', 'rb')),
'action': (None, 'store'),
'path': (None, '/path1')
}
response = requests.post('https://httpbin.org/post', files=multipart_form_data)
print(response.content)
注意None作为纯文本字段的元组中的第一个参数——这是文件名字段的占位符,仅用于文件上传,但对于文本字段,为了提交数据,必须将None作为第一个参数。
具有相同名称的多个字段
如果你需要发布多个具有相同名称的字段,那么你可以将你的有效负载定义为元组的列表(或元组):
multipart_form_data = (
('file2', ('custom_file_name.zip', open('myfile.zip', 'rb'))),
('action', (None, 'store')),
('path', (None, '/path1')),
('path', (None, '/path2')),
('path', (None, '/path3')),
)
流媒体请求API
如果上面的API对你来说不够python化,那么可以考虑使用requests toolbelt (pip install requests_toolbelt),它是核心请求模块的扩展,提供了对文件上传流的支持,以及可以用来代替文件的MultipartEncoder,它还允许你将负载定义为字典、元组或列表。
MultipartEncoder可以用于有或没有实际上传字段的多部分请求。它必须分配给data参数。
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
multipart_data = MultipartEncoder(
fields={
# a file upload field
'file': ('file.zip', open('file.zip', 'rb'), 'text/plain')
# plain text fields
'field0': 'value0',
'field1': 'value1',
}
)
response = requests.post('http://httpbin.org/post', data=multipart_data,
headers={'Content-Type': multipart_data.content_type})
如果你需要发送多个相同名称的字段,或者如果表单字段的顺序很重要,那么可以使用元组或列表来代替字典:
multipart_data = MultipartEncoder(
fields=(
('action', 'ingest'),
('item', 'spam'),
('item', 'sausage'),
('item', 'eggs'),
)
)
推荐文章
- 如何在Python中进行热编码?
- 如何嵌入HTML到IPython输出?
- 在Python生成器上使用“send”函数的目的是什么?
- 是否可以将已编译的.pyc文件反编译为.py文件?
- Django模型表单对象的自动创建日期
- 在Python中包装长行
- 如何计算两个时间串之间的时间间隔
- 我如何才能找到一个Python函数的参数的数量?
- 您可以使用生成器函数来做什么?
- 将Python诗歌与Docker集成
- 提取和保存视频帧
- 使用请求包时出现SSL InsecurePlatform错误
- 如何检索Pandas数据帧中的列数?
- except:和except的区别:
- 错误:“字典更新序列元素#0的长度为1;2是必需的”