How to save an attachment returned from an api?

There is an export api can export all users as an excel file,
I want to save it and use it for import api, how can I do?
Please give me some suggestion~

Hello Jessie! Can you be more specific about what you want to do? Do you mind giving an example workflow across the overall k6 test life cycle?

An early guess:

  1. In the init stage, export the users as a CSV.

  2. (Still in init), combine papaparse with a SharedArray to turn the CSV file into an array that your VUs can reference.

    Example of the exact procedure of this step

  3. In the default function, run your VU code and use the CSV-turned-array data as you wish.

If you want to write the API response to a file, you may need to use an extension.
This post explains why, and links some viable extensions: Write data to file - #2 by imiric

I hope that puts you on the right track! If not, at least that’s two for the process of elimination :slight_smile: .

Really appreciate for your reply!
I’m trying to use k6 for single-interface performance testing, so exporting and importing users are two separate scripts.
Sending a get request when exporting users, and get response like this:



1.Can I get the attachment and save it ?
2.If I save response with file.writeString(path, res.body), how can I use it for importing?

Importing user like this

image

Hello Jessie! Thanks for the context. Unfortunately, I’m still not totally clear about what you want to do, but I can make some guesses. I’ve done some experimenting with k6 so I have a bit of a better idea of capabilities.

Please note two things:

  • All the examples below assume that you understand the stages of the Test life cycle.
  • I’m not saying these are the best solutions! Just ideas. I only tested the solution in option a.

Option a: 1 data file, many VUs

Maybe this is the workflow you want:

  1. Make a GET request to get all items.
  2. Link each virtual user to an item.
  3. Run a test script where each VU does operations for a specific item.

As far as I can tell, a viable option here is the following:

  1. Before the test runs, grab your CSV file.
  2. In the init context, make a SharedArray from the file.
  3. In the init context, set your number of VUs to be the length of the array
  4. In VU code, use the VU number to link that VU’s operations to a specific item in the array.

I’ve adapted this solution from the Data Parametrization and Execution context variable docs.

For example, you can test this out on the k6 API server. I use JSON, but it would be very similar with CSV.

The only problem is that you need to get your file first. A simple way is to make a curl call before the test runs:

If save the following test snippet as sharedArray.js, then these two commands should work in sequence:

curl "https://test-api.k6.io/public/crocodiles" > crocs.json;
k6 run sharedArray.js
import { SharedArray } from "k6/data";
import http from "k6/http";
import exec from "k6/execution";

const data = new SharedArray("crocs", function () {
  return JSON.parse(open("crocs.json"));
});

export const options = {
  vus: data.length,
  duration: "30s",
};

export default function () {
  //make VU count 0-based
  const vu = exec.vu.idInTest - 1;
  http.get(`https://test-api.k6.io/public/crocodiles/${vu}`);
}

For what I can tell, it’s going to be hard to write the CSV to a file and link an item to a unique VU all inside the k6 script, because:

  • init code can’t make http requests currently
  • setUp code can make requests, but it runs after init code
  • The number of VUs is defined in init code, so you can’t use data derived from operations in setUp

If you don’t need to link a VU to a specific item, you have some flexibility:

Option b: Share data without linking VUs to specific items

For this you could:

  1. GET the CSV in setup code, return it as an array.
  2. Run the VU script however you want, passing the returned data from setup.
export function setup() {
  // 2. setup code
}

export default function (data) {
  // 3. VU code
}

Depending on the length of the CSV, this could be less performant than using a SharedArray

Option c: Every VU exports the CSV

If you want every VU to make the GET request, you could do something like this:

import http from 'k6/http';

export default function () {
  const response = http.get('https://test-api.k6.io/public/crocodiles/');
  const crocs = JSON.parse(response.body);
  crocs.forEach((croc) => {
    http.get(`https://test-api.k6.io/public/crocodiles/${croc['id']}/`);
  });
}

Let me know if one of these options works. Good luck!

Thanks for your solution, I really understand what you are trying to say. Unfortunately, I still can’t find a solution to my problem.

To test a single interface without being affected by other interfaces, I run only one script containing a single interface at a time.
Due to the relevance between businesses, I want to save the attachment (Content-Type:application/octet-stream, Content-Disposition:attachment; filename=xxxx.xxx; filename*=UTF-8’xxxx.xxx) in the response of the export interface, and reuse this file for next script.
The problem is that I don’t know how to save this attachment and how to save file stream in the response.

Oh, well, sorry for the unnecessary procedures. I think I understand better now.

This thread might help:

:grinning:
Unfortunately, xk6-file only allow writing string.
image
If I write this uint8array to a file, It can’t be an valid zip file.

Add method in file.go of GitHub - avitalique/xk6-file: k6 extension for writing files
image
Then use it like this:


image

1 Like