No results for

Powered byAlgolia

Data Uploads

Example to execute a load test that will upload a file to the System Under Test (SUT).

The open() function

Using the built-in function open(), we can read the contents of a file given a filename or URL.

Below is a simple example showing how to load the contents of a local file data.json.

data.json
1{
2 "my_key": "has a value"
3}
Loading a local JSON file using open()
1const data = JSON.parse(open('./data.json'));
2
3export default function () {
4 console.log(data.my_key);
5}

If you want to open a binary file you need to pass in "b" as the second argument.

Loading a binary file using open()
1const binFile = open('./image.png', 'b');
2
3export default function () {
4 //...
5}

Multipart request (uploading a file)

Now that you know how to load a local file, let's look at a script that creates a POST request to upload this data to an API endpoint along with a regular text field (field in the example below):

POST upload example
1import http from 'k6/http';
2import { sleep } from 'k6';
3
4const binFile = open('/path/to/file.bin', 'b');
5
6export default function () {
7 const data = {
8 field: 'this is a standard form field',
9 file: http.file(binFile, 'test.bin'),
10 };
11
12 const res = http.post('https://example.com/upload', data);
13 sleep(3);
14}

In the example above we use the http.file() API to wrap the file contents in a FileData object. When passing a JS object as the body parameter to http.post(), or any of the other HTTP request functions, where one of the property values is a FileData a multipart request will be constructed and sent.

Relevant k6 APIs

Advanced multipart request

The previous multipart request example has some limitations:

  • It's not possible to assemble the parts in a specific order, because of the unordered nature of JS objects when they're converted to Golang maps, which k6 uses internally. Uploading files in a specific order is a requirement for some APIs (e.g. AWS S3).
  • It's not possible to upload multiple files as part of the same form field, because JS object keys must be unique.

To address this we suggest using the FormData polyfill for k6.

Here's an example of uploading several binary files and a text file using the polyfill:

Advanced multipart request example
1import http from 'k6/http';
2import { check } from 'k6';
3import { FormData } from 'https://jslib.k6.io/formdata/0.0.2/index.js';
4
5const img1 = open('/path/to/image1.png', 'b');
6const img2 = open('/path/to/image2.jpg', 'b');
7const txt = open('/path/to/text.txt');
8
9export default function () {
10 const fd = new FormData();
11 fd.append('someTextField', 'someValue');
12 fd.append('aBinaryFile', { data: new Uint8Array(img1).buffer, filename: 'logo.png', content_type: 'image/png' });
13 fd.append('anotherTextField', 'anotherValue');
14 fd.append('images', http.file(img1, 'image1.png', 'image/png'));
15 fd.append('images', http.file(img2, 'image2.jpg', 'image/jpeg'));
16 fd.append('text', http.file(txt, 'text.txt', 'text/plain'));
17
18 const res = http.post('https://httpbin.test.k6.io/post', fd.body(), {
19 headers: { 'Content-Type': 'multipart/form-data; boundary=' + fd.boundary },
20 });
21 check(res, {
22 'is status 200': (r) => r.status === 200,
23 });
24}

Note that:

  • Both binary files will be uploaded under the images form field, and the text file will appear last in the request under the text form field.
  • It's required to specify the multipart boundary in the Content-Type header, so you must assemble the header manually as shown.
  • Blob is not supported or implemented. For the same functionality, use a simple object with the fields data, content_type (defaulting to "application/octet-stream") and optionally filename as shown for aBinaryFile above.