准备后端接口
package com.ybchen.controller;
import com.ybchen.utils.JsonData;
import lombok.Data;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @description: csv导出后端接口测试
* @author: Alex
* @create: 2023-11-16 22:41
*/
@RestController
@RequestMapping("/api/v1/csv")
public class CavController {
/**
* 分页接口
*
* @param page 页数
* @param size 一页多少条
* @return
*/
@GetMapping("list")
public JsonData<List<UserInfo>> list(
@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "size", defaultValue = "10") int size
) {
List<UserInfo> resultList = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
resultList.add(new UserInfo(
i,
"陈彦斌___"+page+"_"+i,
page+size+"@qq.com",
new Date()
));
}
return JsonData.buildSuccess(resultList);
}
@Data
public class UserInfo {
/**
* 主键id
*/
private int id;
/**
* 用户名
*/
private String userName;
/**
* 邮箱
*/
private String email;
/**
* 创建时间
*/
private Date createTime;
public UserInfo(int id, String userName, String email, Date createTime) {
this.id = id;
this.userName = userName;
this.email = email;
this.createTime = createTime;
}
}
}
接口数据
{
"code": 0,
"data": [
{
"id": 0,
"userName": "陈彦斌___1_0",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
},
{
"id": 1,
"userName": "陈彦斌___1_1",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
},
{
"id": 2,
"userName": "陈彦斌___1_2",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
},
{
"id": 3,
"userName": "陈彦斌___1_3",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
},
{
"id": 4,
"userName": "陈彦斌___1_4",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
},
{
"id": 5,
"userName": "陈彦斌___1_5",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
},
{
"id": 6,
"userName": "陈彦斌___1_6",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
},
{
"id": 7,
"userName": "陈彦斌___1_7",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
},
{
"id": 8,
"userName": "陈彦斌___1_8",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
},
{
"id": 9,
"userName": "陈彦斌___1_9",
"email": "11@qq.com",
"createTime": "2023-11-16T14:58:48.343+00:00"
}
],
"msg": ""
}
准备后端node环境
下载地址:https://nodejs.cn/download/
切换npm镜像源为淘宝npm镜像
sodu npm install -g cnpm --registry=https://registry.npm.taobao.org
下载node服务
源代码
{
"name": "node-server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.18.3",
"express": "^4.16.3",
"shelljs": "^0.8.2"
}
}
package.json
const express = require('express'),
app = express(),
fs = require('fs'),
shell = require('shelljs'),
// Modify the folder path in which responses need to be stored
folderPath = './Responses/',
defaultFileExtension = 'json', // Change the default file extension
bodyParser = require('body-parser'),
DEFAULT_MODE = 'writeFile',
path = require('path');
// Create the folder path in case it doesn't exist
shell.mkdir('-p', folderPath);
// Change the limits according to your response size
app.use(bodyParser.json({limit: '50mb', extended: true}));
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
app.get('/', (req, res) => res.send('Hello, I write data to file. Send them requests!'));
app.post('/write', (req, res) => {
let extension = req.body.fileExtension || defaultFileExtension,
fsMode = req.body.mode || DEFAULT_MODE,
uniqueIdentifier = req.body.uniqueIdentifier ? typeof req.body.uniqueIdentifier === 'boolean' ? Date.now() : req.body.uniqueIdentifier : false,
currentDate = new Date(),
formattedDate = currentDate.toISOString().split('T')[0], // 获取年月日部分
//文件名
filename = formattedDate,
filePath = `${path.join(folderPath, filename)}.${extension}`,
options = req.body.options || undefined;
fs[fsMode](filePath, req.body.responseData, options, (err) => {
if (err) {
console.log(err);
res.send('Error');
}
else {
res.send('Success');
}
});
});
app.listen(3000, () => {
console.log('ResponsesToFile App is listening now! Send them requests my way!');
console.log(`Data is being stored at location: ${path.join(process.cwd(), folderPath)}`);
});
script.js
仓库地址:https://gitee.com/yenbin_chen/response-to-file-postman
启动node服务
- 下载依赖:npm install
- 启动node服务:node script.js
修改postman脚本
Pre-request Script
// 请求接口前,先保存csv的列名如 responseData,逗号分个, \n用于csv文件内容换行的,csv每行内容在postman的Test里面追加
let opts = {
requestName: request.name || request.url,
fileExtension: 'csv',
mode: 'appendFile',
uniqueIdentifier: false,
responseData: "id,userName,email,createTime\n"
};
pm.sendRequest({
url: 'http://localhost:3000/write',
method: 'POST',
header: 'Content-Type:application/json',
body: {
mode: 'raw',
raw: JSON.stringify(opts)
}
}, function (err, res) {
console.log(res);
});
Test
//备注说明:这里是接口请求之后的处理逻辑,pm.response.json()就是接口返回的json数据:
// { "code": 0,"data": [{"id": 0,"userName": "陈彦斌___1_0","email": "11@qq.com","createTime": "2023-11-16T14:58:48.343+00:00"},{"id": 1,"userName": "陈彦斌___1_1","email": "11@qq.com","createTime": "2023-11-16T14:58:48.343+00:00"}],"msg": ""}
var jsonData = pm.response.json();
console.log(jsonData);
var data = jsonData.data;//拿到这个数据data里的数据,循环调node接口
for(var i=0;i<data.length;i++){
var dataStr = data[i].id + "," + data[i].userName + "," + data[i].email + "," +data[i].createTime + "\n";
let opts = {
requestName: request.name || request.url,
fileExtension: 'csv',
mode: 'appendFile',//这个模式表示往csv里面追加写,单次执行追加写list数据没问题
uniqueIdentifier: false,
responseData: dataStr
};
pm.sendRequest({
url: 'http://localhost:3000/write',
method: 'POST',
header: 'Content-Type:application/json',
body: {
mode: 'raw',
raw: JSON.stringify(opts)
}
}, function (err, res) {
console.log(res);
});
}
演示
循环调postman接口,动态传开始页
我这里开始页,使用占位符:{{page_num}},准备参数,如下
page_num
1
2
3
4
5
注意:因为要循环轮询调后端接口生成csv文件,需要将postman的生成csv的列名去掉,也就是把Pre-request Script逻辑去除,要不然会重复生成列名,等文件生成完后,在手动补充列名即可~~