python requests-toolbelt 生成上传multipart/form-data格式数据
需求背景
想使用requests做一个自动上传的功能,发现这里问题挺多的,比如直接发POST包,或者直接data=二进制流,都会上传失败。我觉得应该挺多人会遇到这个问题,就记录一下。

如上图上传功能,一般分为input标签,非input标签。我这里也不管什么标签,直接抓包看数据流。

Content-Type为传输内容的类型,一般有如下几种:
application/x-www-form-urlencoded:默认的编码方式。 在最早的http post请求中,只支持application/x-www-form-urlencoded,参数都是通过浏览器的url传递。其实是不支持文件上传的,这样有很多不便。
multipart/form-data:用于支持向服务器发送二进制数据,指定传输数据为二进制类型,比如图片、mp3、文件。
text/plain:纯文体的传输。空格转换为 “+” 加号,但不对特殊字符编码。
application/json 等
还有好多类型,建议查谷哥。了解到我们现在要上传multipart/form-data类型的数据,那么我们看看他的格式结构如何。
multipart/form-data 格式结构解析
格式如下:
POST /xxxxxxx/upload/ HTTP/1.1
Host: xxxxx.xxxxxxxxxxxx.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------2385610611750
Content-Length: 1616477
Connection: close
Referer: http://xxxxxx.xxxxxxx.cn/
-----------------------------2385610611750
Content-Disposition: form-data; name="id"
WU_FILE_0
-----------------------------2385610611750
Content-Disposition: form-data; name="name"
app-debug.apk
-----------------------------2385610611750
Content-Disposition: form-data; name="type"
application/octet-stream
-----------------------------2385610611750
Content-Disposition: form-data; name="lastModifiedDate"
2019/10/16 ä¸å8:18:58
-----------------------------2385610611750
Content-Disposition: form-data; name="size"
1615720
-----------------------------2385610611750
Content-Disposition: form-data; name="file"; filename="app-debug.apk"
Content-Type: application/octet-stream
PKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(二进制数据流,很长...)
-----------------------------2385610611750--
格式大致分为如下几种模块:
- 分隔符
- 单 Key = Value 键值对
- 多 Key = Value 键值对
- 结束符


相信你看完我上面那么用心的截图,很容易就看懂它这种分片格式了,懂了格式就好构造了。
使用requests-toolbelt的MultipartEncoder 构造
python-requests是一个实用程序的集合,感觉基本就是用于辅助requests,最常用的功能就是使用MultipartEncoder构造上面说的这种multipart/form-data类型的数据。
官网:https://pypi.org/project/requests-toolbelt/
Demo:
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
def up():
url= 'xxx';
headers={x:x};
multipart_encoder = MultipartEncoder(
fields={
"id": "WU_FILE_0",
"name": "app-debug.apk",
"type": "application/octet-stream",
"lastModifiedDate": "2019/10/16",
"filename": "app-debug.apk",
"Content-Type": "application/octet-stream",
"file": (
"app-debug.apk", open('D:\\xxxx.apk', 'rb'), 'application/octet-stream')
},
boundary='-----------------------------2385610611750'
)
result = requests.post(url, headers=headers, data=multipart_encoder)
boundary放置分隔符,结束符好像会根据这个分隔符自动生成。
单K=V形式都很简单,一看就懂,多K=V形式的就按照他的格式配就好:"file": ("app-debug.apk", open('D:\\xxxx.apk', 'rb'), 'application/octet-stream').
关于boundary的作用
boundary参考:https://stackoverflow.com/questions/3508338/what-is-the-boundary-in-multipart-form-data
boundary示例如下图:

这个boundary的作用就是类似URL提交参数时(www.baidu.com?id=22&name=lisi),作用和&是一模一样的,只不过这个分割的是浏览器自定义(随机生成)的,一般为字母或数字。只要这个分割符不和参数里面的值有一模一样就不有什么问题,服务器接收到整个数据包的时候,只是通过这个分隔符来分割参数,不会去校验这个boundary,只会去校验里面参数值是否符合条件。
Content-Type: multipart/form-data; boundary=--133951685715237
Content-Length: 1617044
Origin: https://www.testin.net
Connection: close
Referer: https://www.testin.net/app/search-list.htm
----133951685715237
Content-Disposition: form-data; name="id"
182832
----133951685715237
Content-Disposition: form-data; name="fileMd5"
35403faf30dc7b90354945c789d649f7
----133951685715237
Content-Disposition: form-data; name="sign"
WU_FILE_0
----133951685715237--
格式如上,boundary=--133951685715237,只有两个--,参数分割的时候----133951685715237,有四个----,最后标记结束符的时候还需要多两个--,----133951685715237--。
如果是使用requests_toolbelt的话,只需要设置和Content-Type: multipart/form-data; boundary=--133951685715237和boundary=xxx即可,因为它会自动帮助你调整格式。
参考文章
https://www.jianshu.com/p/0023bb7afddb
https://blog.csdn.net/xuezhangjun0121/article/details/82023320
https://blog.csdn.net/liyingke112/article/details/70233776
https://my.oschina.net/lykops/blog/1506911
https://stackoverflow.com/questions/3508338/what-is-the-boundary-in-multipart-form-data
python requests-toolbelt 生成上传multipart/form-data格式数据的更多相关文章
- VUE axios 发送 Form Data 格式数据请求
axios 默认是 Payload 格式数据请求,但有时候后端接收参数要求必须是 Form Data 格式的,所以我们就得进行转换.Payload 和 Form Data 的主要设置是根据请求头的 C ...
- Python Requests库 form-data 上传文件操作
请求数据示例: ------WebKitFormBoundaryKLoWgrA4O40MayHM Content-Disposition: form-data; name="id" ...
- [python][flask] Flask 图片上传与下载例子(支持漂亮的拖拽上传)
目录 1.效果预览 2.新增逻辑概览 3.tuchuang.py 逻辑介绍 3.1 图片上传 3.2 图片合法检查 3.3 图片下载 4.__init__.py 逻辑介绍 5.upload.html ...
- python Django之文件上传
python Django之文件上传 使用Django框架进行文件上传共分为俩种方式 一.方式一 通过form表单进行文件上传 #=================================== ...
- python接收html页面上传的文件
使用的 flask, 没有安装的先安装 pip install flask 示例代码:示例没有自动创建静态文件夹,需要自己在同级 创建一个名为 static 的文件夹来存放上传的文件 示例展示为图片 ...
- httprunner学习25-文件上传multipart/form-data
前言 httprunner上传文件接口,其实跟requests上传文件的接口是一样的,之前在python接口系列里面有案例 python接口自动化16-multipart/form-data上传图片 ...
- 七牛云存储Python SDK使用教程 - 上传策略详解
文 七牛云存储Python SDK使用教程 - 上传策略详解 七牛云存储 python-sdk 七牛云存储教程 jemygraw 2015年01月04日发布 推荐 1 推荐 收藏 2 收藏,2.7k ...
- python+ajaxFileUpload 无刷新上传文件
需要准备文件 http://pan.baidu.com/s/1bp4N3nL qqi0 html <script src="{% static 'js/jquery.js' %}& ...
- Burp Post、Get数据包转为上传multipart/form-data格式数据包
方法一: 新建一个网页进行上传,代码代码如下: <html> <head></head> <body> <form method="po ...
随机推荐
- 【Offer】[56-2] 【数组中唯一只出现一次的数字】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 在一个数组中除一个数字只出现一次之外,其他数字都出现了三次.请找出那个只出现一次的数字 [牛客网刷题地址]无 思路分析 如果一个数字出现 ...
- Mac环境IntelliJ IDEA配置JDK提示The selected directory is not a valid home for JDK
笔者使用mac配置如下: 硬件环境:MacBook Pro 操作系统:MacOS Sierra 10.13.6 开发工具:IntelliJ IDEA 2016.x JDK版本:已有Open JDK 8 ...
- CentOS 7 下的网络配置工具
之前在CentOS 6下编辑网卡,直接使用setup工具就可以了. 但在新版的CentOS 7里,setuptool已经没有网络编辑组件了,取而代之的是NetworkManager Text User ...
- application.properties 乱码 (已验证)
1.打开Eclipse或MyEclipse 2.选择window-Preferences-content Types-Text-Java Properties File 3.将Java Propert ...
- 第二次作业:使用Packet Tracer分析应用层协议(DNS、FTP、DHCP、SMTP、POP3)
0 个人信息 张樱姿 201821121038 计算1812 1 实验目的 熟练使用Packet Tracer工具.分析抓到的应用层协议数据包,深入理解应用层协议,包括语法.语义.时序. 2 实验内容 ...
- 【PTA】浙江大学数据结构慕课 课后编程作业 03-树1 树的同构
题目内容 给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是"同构"的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右 ...
- 年年有余之java求余的技巧集合
背景 传说里玉皇大帝派龙王马上降雨到共光一带,龙王接到玉皇大帝命令,立马从海上调水,跑去共光施云布雨,但粗心又着急的龙王不小心把海里的鲸鱼随着雨水一起降落在了共光,龙王怕玉皇大帝责怪,灵机一动便声称他 ...
- 【linux】【docker】docker私服安装
前言 系统环境:Centos7.jdk1.8 docker私服:可以把项目通过dockerfile文件build成docker镜像,供其他环境拉取.部署在本地,私有化. 安装 dockerHUB私服 ...
- MySQL中对字段内容为Null的处理
使用如下指令,意思就是 select IFNULL(jxjy,0) AS jxjy from yourTable ifnull(a,b) 意思是指:如果字段a为null,就等于b if( sex = ...
- pathlib模块
一.pathlib库官方定义 pathlib 是Python内置库,Python 文档给它的定义是 Object-oriented filesystem paths(面向对象的文件系统路径).path ...