上传文件接口调试

最近在写脚本时有一个功能是上传附件,也趁这个机会学习了下对于上传文件类的接口该如何进行传参

本次介绍2种方式来上传附件:一种是通过jmeter;另一种是通过python的requests库

接口参数分析

在讲具体方法之前,先来分析下这次上传附件接口的headers与携带的参数信息

headers种主要看content-type,这个请求中的content-type如下

content-type: multipart/form-data; boundary=----WebKitFormBoundaryKtD3qxHwCR9S9Wdy
 
 
 查了一些资料,大概意思是说:数据以multipart/form-data编码,boundary 用于分割不同的字段
继续看下参数是如何的,可能就理解上面说的boundary用于分割字段是什么意思了,chrome控制台下显示的参数信息如下
 
------WebKitFormBoundaryKtD3qxHwCR9S9Wdy
Content-Disposition: form-data; name="type"
 
3
------WebKitFormBoundaryKtD3qxHwCR9S9Wdy
Content-Disposition: form-data; name="file"; filename="test.jpg"
Content-Type: image/jpeg
 
 
------WebKitFormBoundaryKtD3qxHwCR9S9Wdy--


 

 

 

 

 

可以看到消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制);

如果传输的是文件,还要包含文件名和文件类型信息;

消息主体最后以 --boundary-- 标示结束;

另外boundary每次都是随机生成的!!!

更多内容请看:https://imququ.com/post/four-ways-to-post-data-in-http.html

1. jmeter上传附件

以我这个请求为例,来说明一下如何填写请求参数,先把请求body再次放在在这里

------WebKitFormBoundaryKtD3qxHwCR9S9Wdy
Content-Disposition: form-data; name="type"
 
3
------WebKitFormBoundaryKtD3qxHwCR9S9Wdy
Content-Disposition: form-data; name="file"; filename="test.jpg"
Content-Type: image/jpeg
 
 
------WebKitFormBoundaryKtD3qxHwCR9S9Wdy--

 

 

 

 

 

 

如果请求body中除了需要上传文件外,还需要上传其他参数,如上面的第一部分,表示有个参数名为"type",它的值为3,需要把它填入jmeter的【参数】中

在【文件上传】中填写附件的参数信息

(1) 勾选【对POST使用multipart/form-data】

(2) 文件名称:附件绝对路径

(3) 参数名称:这个根据你在chrome控制台看到参数名称来填写,回头看上面贴出来的请求body

第二部分就是对上传文件的文件名和文件类型的描述,观察内容可以发现

name=“file”,所以这里的参数名称就填写“file”(填错的话,一般会报错的)

Content-Type为image/jpeg,所以jmeter中的MIME类型就填写“image/jpeg”

ps.关于headers的一点说明:刚开始的时候,我一直想着在信息头管理器中加上固定的 content-type: multipart/form-data; boundary=----WebKitFormBoundaryKtD3qxHwCR9S9Wdy

 但是实际运行脚本时总是报错,查看结果树中的请求头,也并不是自己定义的这个boundary,貌似自己生成了一个boundary

  后来把请求头中的content-type去掉后,再次运行就成功了

 综上,在jmeter中进行文件上传的请求脚本就写好了

2. 使用python的requests库上传文件

 在使用requests上传文件时,可以先看看官方文档的一段描述:

https://requests.readthedocs.io/zh_CN/latest/user/quickstart.html#post-multipart-encoded

Requests 使得上传多部分编码文件变得很简单:

>>> url = 'http://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')}

>>> r = requests.post(url, files=files)
>>> r.text
{
  ...
  "files": {
    "file": "<censored...binary...data>"
  },
  ...
}

你可以显式地设置文件名,文件类型和请求头:

>>> url = 'http://httpbin.org/post'
>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}

>>> r = requests.post(url, files=files)
>>> r.text
{
  ...
  "files": {
    "file": "<censored...binary...data>"
  },
  ...
}

通过这个例子,可以知道requests上传文件是通过files关键字来完成的:先定义一个变量files,它是一个字典,key=file,value则是打开的二进制文件;然后发送post请求时,带上file参数即可

拿我这次的请求来说,如下

files = {"file": ("/data/image/test.jpg", 'rb'))}
payload={
  type: 3 } response
= requests.post(url, files=files, data=payload, headers=headers)

payload中定义的是请求body中的type参数;files是本次要上传的文件;

发送post请求时,需要用files关键字发送文件,用data关键字发送payload

执行这段脚本能够得到和jmeter同样的结果

接下来查看下发送出的请求携带的请求头是什么样的

print(response.request.headers)

结果如下

{
    'User-Agent': 'python-requests/2.22.0',
    'Accept-Encoding': 'gzip, deflate',
    'Accept': '*/*',
    'Connection': 'keep-alive','Content-Length': '110824',
    'token': 'sImDk2YzBkOTkzNFwiLFwiZW1haWxcIjpcIjgxZjcwZjJkOWFmODA1MD',
    'Content-Type': 'multipart/form-data; boundary=59a681a11824f2dd578becdd4195cf9b'
}

可以发现,python自己给它补全了Content-Type,并且boundary也是自己生成的一段字符

 至于如何自己定义boundary还得再研究研究

posted @ 2020-05-12 21:58  我是冰霜  阅读(4424)  评论(0编辑  收藏  举报