Jmeter附件名称参数化
上一篇 / 下一篇 2018-04-23 09:31:01 / 个人分类:Jmeter
碰到代码层的问题还是怕怕的,好在总是有高人愿意分享解决的问题。百度了一下问题,一下找到了一篇。
Jmeter附件名称参数化
转自 https://blog.csdn.net/defonds/article/details/41593253?utm_source=tuicool&utm_medium=referral
问题描述
文件上传时,用户定义 Content-Disposition 是失效的。笔者在写压力测试脚本的时候,有个上传页面,服务器是根据用户传过来的 Content-Disposition 里的 filename 值来定义保存文件的文件名的。但是测试人员不可能为每一次请求都准备一个不同的文件(这个工作量海了去了),所以 JMeter 传给服务器的 Content-Disposition 里的 filename 必须是随机而不重复的。
有人问,用户真实上传时,浏览器传给服务器的 filename 也是上传文件名吗?不是的,js 这样修改的 filename:
[javascript] view plain copy
- uploader.onBeforeUploadItem = function (item) {
- //修改名字
- var timeStamp = new Date().getTime();
- var fileName = item.file.name;
- item.file.name = timeStamp + fileName.substr(fileName.lastIndexOf('.'));
- var day = $filter('date')(new Date(), 'yyyyMMdd');
- item.url = [item.url, "batchImport", item.importType, day, session.userId].join("/");
- };
笔者尝试了多种办法,试图修改服务器接收到的 filename 值,结果都失败了。笔者尝试的办法有:
1. 添加 HTTP 参数
如图所示,我们期待服务器接收到的 filename 值是 00004000.xls,而不是 00000000.xls。
结果服务器接收到的是 00000000.xls。服务器返回给客户端的存储路径为证:/batchImport/merAdd/20141128/1/00000000.xls。查看本次 HTTP 请求,可以看到以下信息:
POST http://serverIP/upload/batchImport/merAdd/20141128/1
POST data:
--DoZtX5jrOIxJTocysPzYJ1WVqtoagXMQHHqho4i
Content-Disposition: form-data; name="Content-Disposition"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit
form-data; name="14170058206940.xls"; filename="00004000.xls"
--DoZtX5jrOIxJTocysPzYJ1WVqtoagXMQHHqho4i
Content-Disposition: form-data; name="file"; filename="00000000.xls"
Content-Type: application/vnd.ms-excel
Content-Transfer-Encoding: binary
<actual file content, not shown here>
--DoZtX5jrOIxJTocysPzYJ1WVqtoagXMQHHqho4i--
Cookie Data:
$Version=0; JSESSIONID=AC79777AEFE5AFC690623FCCB09E5DD5; $Path=/
Request Headers:
Connection: keep-alive
Content-Length: 34786
Content-Type: multipart/form-data; boundary=DoZtX5jrOIxJTocysPzYJ1WVqtoagXMQHHqho4i
Host: serverIP
User-Agent: Apache-HttpClient/4.2.6 (java 1.5)
看来 JMeter 把我们的 Content-Disposition 参数名字都丢了。
2. 添加 HTTP 信息头管理器
如图所示,我们期待服务器接收到的 filename 值是 40004000.xls,而不是 00000000.xls。
然后我们发次请求,然后查看本次 HTTP 请求,可以看到以下信息:
POST http://serverIP/upload/batchImport/merAdd/20141128/1
POST data:
--BNKvCNweqwpTJToYINcDn6JJfzjazBE550a-
Content-Disposition: form-data; name="file"; filename="00000000.xls"
Content-Type: application/vnd.ms-excel
Content-Transfer-Encoding: binary
<actual file content, not shown here>
--BNKvCNweqwpTJToYINcDn6JJfzjazBE550a---
Cookie Data:
$Version=0; JSESSIONID=49AB53310FB7241B5544B4E747A58F80; $Path=/
Request Headers:
Connection: keep-alive
Content-Disposition: form-data; name="file"; filename="40004000.xls"
Content-Length: 34535
Content-Type: multipart/form-data; boundary=BNKvCNweqwpTJToYINcDn6JJfzjazBE550a-
Host: serverIP
User-Agent: Apache-HttpClient/4.2.6 (java 1.5)
这次 JMeter 没有把我们的 Content-Disposition 弄丢,它出现在了 Request Headers 里边。但是服务器貌似读取的是 POST data 中 Content-Disposition 里的那个 filename。有服务器返回给客户端的存储路径为证:/batchImport/merAdd/20141128/1/00000000.xls。
3. 使用 BeanShell
如图所示,我们期待服务器接收到的 filename 值是 40004004.xls,而不是 00000000.xls。我们怀着期待的心情再次向服务器发起请求。请求如下:
POST http://serverIP/upload/batchImport/merAdd/20141128/1
POST data:
--LWS2eUVPPPuDxcfT7dS4RpqQJe2uP_0lAme6Qx2Q
Content-Disposition: form-data; name="file"; filename="00000000.xls"
Content-Type: application/vnd.ms-excel
Content-Transfer-Encoding: binary
<actual file content, not shown here>
--LWS2eUVPPPuDxcfT7dS4RpqQJe2uP_0lAme6Qx2Q--
Cookie Data:
$Version=0; JSESSIONID=81514F48024CE0B4CB53DB0CBC283C11; $Path=/
Request Headers:
Connection: keep-alive
Content-Length: 34543
Content-Type: multipart/form-data; boundary=LWS2eUVPPPuDxcfT7dS4RpqQJe2uP_0lAme6Qx2Q
Host: serverIP
User-Agent: Apache-HttpClient/4.2.6 (java 1.5)
结果是不管是前置 BeanShell,还是 BeanShell 监听器,显然对于我们的需求无能为力。
向万能的谷歌求助,得到的结果基本都是 It's impossible。
最后笔者怀着郁闷的心情去找这个项目的责任人,试图说服他,服务器不应该以客户端传来的 filename 对保存文件进行命名,应该有自己的一套随机生成文件名的规则,得到的答复却是:NO。
万般无奈之下,笔者只好去看 JMeter 的源代码了。好嘛,JMeter 2.12 的源代码(src 目录下的纯 *.java 文件)足足有 6.75 MB。而且还是用 Ant 代码管理的,黑压压的看着森人。哎,不爽也得看,没办法啊,谁让咱要吃性能测试这碗饭呢,工作总是要继续的吧。
硬着头皮看了一下午,结果很不幸,发现 JMeter 是把 Content-Disposition 里的 filename 写死的,它压根儿就没想留给用户对 filename 进行参数化途径!
比如 org.apache.jmeter.protocol.http.sampler.PostWriter 的 writeStartFileMultipart 方法是这样写死的:
[java] view plain copy
- /**
- * Write the start of a file multipart, up to the point where the
- * actual file content should be written
- */
- private void writeStartFileMultipart(OutputStream out, String filename,
- String nameField, String mimetype)
- throws IOException {
- write(out, "Content-Disposition: form-data; name=\""); // $NON-NLS-1$
- write(out, nameField);
- write(out, "\"; filename=\"");// $NON-NLS-1$
- write(out, new File(filename).getName());
- writeln(out, "\""); // $NON-NLS-1$
- writeln(out, "Content-Type: " + mimetype); // $NON-NLS-1$
- writeln(out, "Content-Transfer-Encoding: binary"); // $NON-NLS-1$
- out.write(CRLF);
- }
虽然很气愤,但觉着总算没来错地方,继续看源码。
查看 PostWriter 的单元测试代码 org.apache.jmeter.protocol.http.sampler.PostWriterTest,在测试 sendPostData 方法里有以下语句:
postWriter.setHeaders(connection, sampler);
postWriter.sendPostData(connection, sampler);
也就是说先写头,再写 post 包体。org.apache.jmeter.protocol.http.sampler.HTTPJavaImpl 的 sample 方法也印证了这个:
[java] view plain copy
- try {
- conn = setupConnection(url, method, res);
- // Attempt the connection:
- savedConn = conn;
- conn.connect();
- break;
- } catch (BindException e) {
- if (retry >= MAX_CONN_RETRIES) {
- log.error("Can't connect after "+retry+" retries, "+e);
- throw e;
- }
- log.debug("Bind exception, try again");
- if (conn!=null) {
- &nb
TAG:
标题搜索
日历
|
|||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
1 | 2 | 3 | 4 | ||||||
5 | 6 | 7 | 8 | 9 | 10 | 11 | |||
12 | 13 | 14 | 15 | 16 | 17 | 18 | |||
19 | 20 | 21 | 22 | 23 | 24 | 25 | |||
26 | 27 | 28 | 29 | 30 | 31 |
我的存档
数据统计
- 访问量: 43145
- 日志数: 54
- 文件数: 1
- 建立时间: 2018-02-24
- 更新时间: 2019-11-21