之前写过一篇博客, 说的如何 python 如何通过 http 下载文件, 今天写一篇博客来介绍如下, python 如何通过 request 库实现上传文件
这里主要是解决 multipart/form-data 这种格式的文件上传, 基本现在 http 协议上传文件基本上都是通过这种格式上传
一, 思路
一般情况下, 如果我们往一个地址上传文件, 则必须要登陆, 登陆成功后, 拿到 cookies, 然后在上传文件的请求携带这个 cookies.
然后我们就需要通过浏览器在网站上传文件, 记得, 这个时候抓包要使用 fiddler 工具, 会更加保险, 然后按照 fiddler 抓到包组装我们的上传文件的 post 请求
大家把握一个原则就是: 在 post 请求中, 用 files 参数来接受文件对象相关的参数, 通过 data/JSON 参数接受 post 请求体的其他参数即可.
二, 实现
1, 使用 requests.session() 对象登陆网站, 这里主要为了方便, 下次直接用这个对象发送 post 上传文件的请求即可, 不需要我们在请求体中添加 cookies
- import requests
- s = requests.session()
- res1 = s.post(
- url="http://10.222.222.7/src/welcome.php",
- headers = {
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Accept-Encoding": "gzip, deflate",
- "Accept-Language": "zh-CN,zh;q=0.9",
- "Cache-Control": "max-age=0",
- "Connection": "keep-alive",
- "Content-Type": "application/x-www-form-urlencoded",
- "Host": "10.222.222.7",
- "Origin": "http://10.222.222.7",
- "Referer": "http://10.222.222.7/src/welcome.php",
- "Upgrade-Insecure-Requests": "1",
- "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36"
- },
- data = {
- "name": "admin",
- "password": "admin",
- "button": "登录",
- "opr": "login",
- },
- # 这里配置了代理, 因为我的操作安装了 fiddler, 这个你们没有说一定要弄
- proxies={
- "http": "http://127.0.0.1:8888",
- "https": "http://127.0.0.1:8888"
- }
- )
2, 手动上传, 通过 fiddler 抓包, 分析 http 请求的参数
上面是 http 请求的 raw 格式, 我们一般会看 webForms 格式的 http 请求
3, 分析完成后, 我们可以看下代码
- import JSON
- file = {
- "sample_file": open("D:\\abdi\\37571.pcap", "rb"),
- "Content-Type": "application/octet-stream",
- "Content-Disposition": "form-data",
- "filename" : "3757.pcap"
- }
- # #
- res = s.post(
- url="http://10.222.222.7/src/system_sample.php/system_sample/add",
- headers = {
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Accept-Encoding": "gzip, deflate",
- "Accept-Language": "zh-CN,zh;q=0.9",
- "Cache-Control": "max-age=0",
- "Connection": "keep-alive",
- # "Content-Type": "multipart/form-data",
- "Host": "10.222.222.7",
- "Origin": "http://10.222.222.7",
- "Referer": "http://10.222.222.7/src/html.php/html/system_samples",
- "Upgrade-Insecure-Requests": "1",
- "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36"
- },
- files = file,
- data = {
- "sample_name" : "37571.pcap",
- "owner_group" : "/data/atp/pcap/custom/test",
- "type" : "1",
- "sample_file_path" : "",
- "description_file_path" : "",
- # "description_file":""
- },
- proxies = {
- "http":"http://127.0.0.1:8888",
- "https":"http://127.0.0.1:8888"
- }
- )
这里有三个关键的地方
a,data 参数, 注意看 k 值和抓包中的对比
不同的网站的 name 的值可能不一样, 但是大部分大家都会用 file, 但是有时候开发人员也不会按照常规套路来做, 所以我们不能想当然就认为是 files. 要通过抓包分析
这个值一般就是上传后的文件的名称; 其他几个参数的意义就不重要了, 你要根据具体的情况分析组装上传就可以了
b,files 参数, 这里很关键, 这里就是我们上传的文件对象了
sample_file 这个参数就代表文件文件对象
c,content-type 参数, 如果我们通过 form-data 的方式上传文件, 我们组装 post 请求的时候, headers 这个参数中一定不能要包括这个值, 由 requests 库帮添加这个元素
如果我们自作聪明, 会导致上传失败的, 这里非常重要!!!
大家可以看到, 我在代码中没有传递 content-type 这个参数, 但是抓包是有这个参数的, 所以这个参数我们一定不能加
实际抓包有这个参数
4, 实际上传抓包验证即可, 和浏览器上传略有不同, 但是不影响上传
来源: https://www.cnblogs.com/bainianminguo/p/12099532.html