如何用Python的requests库发送含数组的multipart/form-data请求?
如何用Python的requests库发送带重复name字段的multipart/form-data请求?
有一个接收multipart/form-data类型HTTP请求的接口,可接受的请求体示例如下:
----------------------------033392576939750140334380 Content-Disposition: form-data; name="file" filename="dummy_file.txt" Some dummy file here. ----------------------------033392576939750140334380 Content-Disposition: form-data; name="years" 2019 ----------------------------033392576939750140334380 Content-Disposition: form-data; name="years" 2020 ----------------------------033392576939750140334380
可以看到,请求中通过重复的years字段传递数组值。但使用Python的requests库发送时,常规方法无法满足需求,以下是尝试过的几种无效方式:
尝试1:直接传入列表作为值
requests.post( "http://some.site/some-endpoint/", files={ "years": [2019, 2020], "file": ("dummy_file.txt", open("dummy_file.txt", "rb")), }, )
报错:TypeError: a bytes-like object is required, not 'list'
尝试2:将数组转为字符串传入
requests.post( "http://some.site/some-endpoint/", files={ "years": (None, "2019, 2020"), "file": ("dummy_file.txt", open("dummy_file.txt", "rb")), }, )
生成的请求体:
--88c0aa2588fb3ca9b1e3c9c6cf625677 Content-Disposition: form-data; name="years" 2019, 2020 --88c0aa2588fb3ca9b1e3c9c6cf625677 Content-Disposition: form-data; name="file"; filename="dummy_file.txt" Some dummy file here. --88c0aa2588fb3ca9b1e3c9c6cf625677--
years被转为单个字符串,不符合接口要求。
尝试3:使用索引命名字段
requests.post( "http://some.site/some-endpoint/", files={ "years[0]": (None, "2020"), "years[1]": (None, "2019"), "file": ("dummy_file.txt", open("dummy_file.txt", "rb")), }, )
生成的请求体:
--989f55fc01395402654f4275d11e8735 Content-Disposition: form-data; name="years[0]" 2020 --989f55fc01395402654f4275d11e8735 Content-Disposition: form-data; name="years[1]" 2019 Content-Disposition: form-data; name="file"; filename="dummy_file.txt" Some dummy file here. --989f55fc01395402654f4275d11e8735
每个数组元素对应不同的字段名,不符合需求。
正确解决方案
requests的files参数除了接受字典,还支持传入列表。列表中的每个元素是一个元组,格式为(字段名, 文件信息),这样就能实现重复字段名的需求:
import requests with open("dummy_file.txt", "rb") as f: requests.post( "http://some.site/some-endpoint/", files=[ ("years", (None, "2019")), ("years", (None, "2020")), ("file", ("dummy_file.txt", f)), ] )
说明:
- 对于非文件类型的字段(如
years),文件信息部分用(None, 值)的格式,None表示没有文件名,第二个参数是字段的字符串值。 - 使用
with语句管理文件句柄,避免资源泄漏。
这样生成的请求体就会和接口要求的结构一致,包含两个name="years"的字段。
内容的提问来源于stack exchange,提问作者Dmytro
相关产品推荐
相关产品推荐

