如何使用Python requests发送带JSON和文件的form-data请求
问题描述
需要用Python的requests库迁移一个form-data请求,该请求包含两个部分:
- 名为
input的字段,文件名是blob,类型为application/json的JSON数据 - 名为
file的字段,文件名为contractFile.pdf,类型为application/pdf的PDF文件
尝试了两种实现方式,均收到API报错:"Content type application/octet-stream not supported",但检查请求头并未发现该类型,搞不懂为啥会出现这个问题。
尝试的代码1
url = {url}:{host}/{end_point} multipart_data = MultipartEncoder( fields={ 'input': 'name', 'file': ('contractFile.pdf', open('contractFile.pdf', 'rb'), 'application/pdf') } ) r = requests.post(url, data=multipart_data, auth=('admin', 'admin'), headers={ 'Content-Type': multipart_data.content_type})
尝试的代码2
url = {url}:{host}/{end_point} files = {'file': ( 'contractFile.pdf', open('contractFile.pdf', 'rb'), 'application/pdf' )} payload = {'input': {'"name": "template20"'}} json.dumps(list(payload)) r = requests.post(url, data=payload, auth=('admin', 'admin'), files=files) print(r.text, '\n\n', r.headers['content-type'], '\n', r.headers['accept'])
解决方案
错误根源
application/octet-stream是工具默认兜底的内容类型,当requests或MultipartEncoder无法识别字段的指定类型时就会触发。你的问题核心是input字段没有按要求设置文件名、内容类型,且JSON数据格式错误。
正确实现方式
方式一:用MultipartEncoder(推荐)
from requests_toolbelt.multipart.encoder import MultipartEncoder import requests import json url = "{url}:{host}/{end_point}" # 构造合法的JSON字符串 input_json_str = json.dumps({"name": "template20"}) multipart_data = MultipartEncoder( fields={ # 严格按要求指定input字段的文件名、内容、类型 'input': ('blob', input_json_str, 'application/json'), 'file': ('contractFile.pdf', open('contractFile.pdf', 'rb'), 'application/pdf') } ) r = requests.post(url, data=multipart_data, auth=('admin', 'admin'), headers={ 'Content-Type': multipart_data.content_type}) print(r.text)
方式二:用requests原生files参数
requests的files参数可以统一处理所有form-data字段,包括非文件类型的字段:
import requests import json url = "{url}:{host}/{end_point}" input_json_str = json.dumps({"name": "template20"}) # 所有字段都放在files里,明确每个字段的元组信息 files = { 'input': ('blob', input_json_str, 'application/json'), 'file': ('contractFile.pdf', open('contractFile.pdf', 'rb'), 'application/pdf') } r = requests.post(url, auth=('admin', 'admin'), files=files) print(r.text)
原代码问题拆解
- 第一种代码:
input字段只传了'name'字符串,既没指定文件名blob,也没声明application/json类型,MultipartEncoder会默认把它设为text/plain,不符合API要求;同时JSON数据本身也不对,应该是完整的JSON对象而非单个字符串。 - 第二种代码:
payload格式完全错误,{'input': {'"name": "template20"'}}是把JSON字符串嵌套成字典值,而且json.dumps(list(payload))没赋值给变量等于白执行;另外用data参数传payload会被编码成application/x-www-form-urlencoded,不是form-data的一部分,导致API识别异常触发兜底类型。
内容的提问来源于stack exchange,提问作者Resurrect1on
相关产品推荐
相关产品推荐

