准备后端接口
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逻辑去除,要不然会重复生成列名,等文件生成完后,在手动补充列名即可~~