数据上传
执行负载测试的示例,该测试将文件上传到被测系统 (SUT)。
open() 函数
使用内置函数 open()
,我们可以读取给定文件名或 URL 的文件内容。
下面是一个简单的示例,展示如何加载本地文件 data.json
的内容。
{
"my_key": "has a value"
}
const data = JSON.parse(open('./data.json'));
export default function () {
console.log(data.my_key);
}
如果要打开二进制文件,需要将 "b"
作为第二个参数传入。
const binFile = open('./image.png', 'b');
export default function () {
//...
}
Multipart 请求(文件上传)
既然您知道如何加载本地文件,接下来我们看看一个脚本,它创建一个 POST 请求,将这些数据以及一个普通文本字段(如下例中的 field
)上传到一个 API 端点。
import http from 'k6/http';
import { sleep } from 'k6';
const binFile = open('/path/to/file.bin', 'b');
export default function () {
const data = {
field: 'this is a standard form field',
file: http.file(binFile, 'test.bin'),
};
const res = http.post('https://example.com/upload', data);
sleep(3);
}
在上面的示例中,我们使用 http.file() API 将文件内容包装在 FileData 对象中。当将 JS 对象作为请求体参数传递给 http.post() 或任何其他 HTTP 请求函数时,如果其中一个属性值是 FileData,则将构建并发送 multipart 请求。
相关的 k6 API
高级 multipart 请求
前面的 multipart 请求示例有一些限制
- 由于 JS 对象在转换为 k6 内部使用的 Golang map 时无序,因此无法按照特定顺序组合各个部分。按照特定顺序上传文件是某些 API(例如 AWS S3)的要求。
- 无法将多个文件作为同一个表单字段的一部分上传,因为 JS 对象键必须是唯一的。
为了解决这个问题,我们建议使用 k6 的 FormData
polyfill for k6。
以下是使用 polyfill 上传多个二进制文件和一个文本文件的示例
import http from 'k6/http';
import { check } from 'k6';
import { FormData } from 'https://jslib.k6.io/formdata/0.0.2/index.js';
const img1 = open('/path/to/image1.png', 'b');
const img2 = open('/path/to/image2.jpg', 'b');
const txt = open('/path/to/text.txt');
export default function () {
const fd = new FormData();
fd.append('someTextField', 'someValue');
fd.append('aBinaryFile', {
data: new Uint8Array(img1).buffer,
filename: 'logo.png',
content_type: 'image/png',
});
fd.append('anotherTextField', 'anotherValue');
fd.append('images', http.file(img1, 'image1.png', 'image/png'));
fd.append('images', http.file(img2, 'image2.jpg', 'image/jpeg'));
fd.append('text', http.file(txt, 'text.txt', 'text/plain'));
const res = http.post('https://quickpizza.grafana.com/api/post', fd.body(), {
headers: { 'Content-Type': 'multipart/form-data; boundary=' + fd.boundary },
});
check(res, {
'is status 200': (r) => r.status === 200,
});
}
请注意
- 两个二进制文件都将上传到
images
表单字段下,文本文件将显示在请求中的text
表单字段下最后。 - 需要在
Content-Type
头部中指定 multipart boundary,因此您必须手动组装头部,如所示。 - 不支持或未实现 Blob。要获得相同的功能,请使用一个简单的对象,包含字段
data
、content_type
(默认为“application/octet-stream”)和可选的filename
,如上面的aBinaryFile
所示。