菜单
文档breadcrumb arrow Grafana k6breadcrumb arrow 示例breadcrumb arrow 数据上传
开源

数据上传

执行负载测试的示例,该测试将文件上传到被测系统 (SUT)。

open() 函数

使用内置函数 open(),我们可以读取给定文件名或 URL 的文件内容。

下面是一个简单的示例,展示如何加载本地文件 data.json 的内容。

json
{
  "my_key": "has a value"
}
JavaScript
const data = JSON.parse(open('./data.json'));

export default function () {
  console.log(data.my_key);
}

如果要打开二进制文件,需要将 "b" 作为第二个参数传入。

JavaScript
const binFile = open('./image.png', 'b');

export default function () {
  //...
}

Multipart 请求(文件上传)

既然您知道如何加载本地文件,接下来我们看看一个脚本,它创建一个 POST 请求,将这些数据以及一个普通文本字段(如下例中的 field)上传到一个 API 端点。

JavaScript
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 上传多个二进制文件和一个文本文件的示例

JavaScript
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。要获得相同的功能,请使用一个简单的对象,包含字段 datacontent_type(默认为“application/octet-stream”)和可选的 filename,如上面的 aBinaryFile 所示。