实现是 前端轮询 /import/progress/{taskId} 接口 taskId 是前端生成的唯一key。 也可以用webSocket 实现

实体类
java
package com.ruoyi.materials.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
private int code;
private String msg;
private T data;
public static <T> Result<T> success(T data) {
return new Result<>(200, "success", data);
}
public static <T> Result<T> progress(T progress) {
return new Result<>(200, "importing", progress);
}
}
工具类
java
package com.ruoyi.materials.until;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 导入进度缓存(正式环境建议用 Redis,这里用内存方便测试)
*/
@Component
public class ImportProgressCache {
// key: taskId 任务ID, value: 进度 0~100
private final Map<String, Integer> progressMap = new ConcurrentHashMap<>();
// 更新进度
public void setProgress(String taskId, int progress) {
progressMap.put(taskId, progress);
}
// 获取进度
public Integer getProgress(String taskId) {
return progressMap.getOrDefault(taskId, 0);
}
// 删除进度
public void removeProgress(String taskId) {
progressMap.remove(taskId);
}
}
controller
java
package com.ruoyi.web.controller.materials;
import com.ruoyi.materials.domain.Result;
import com.ruoyi.materials.until.ImportProgressCache;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.BufferedReader;
import java.io.InputStreamReader;
@RestController
@RequestMapping("/import")
@RequiredArgsConstructor
public class ImportController {
private final ImportProgressCache importProgressCache;
/**
* 1. 文件导入接口(异步执行)
* @param file 上传文件
* @param taskId 任务ID(前端/Postman生成)
*/
@PostMapping("/file")
public Result<String> importFile(
@RequestParam("file") MultipartFile file,
@RequestParam("taskId") String taskId
) throws Exception {
if (file.isEmpty()) {
return new Result<>(500, "文件不能为空", null);
}
// 异步执行导入(不阻塞前端)
new Thread(() -> {
try {
// 初始化进度 0
importProgressCache.setProgress(taskId, 0);
// 读取文件(模拟Excel/CSV解析)
BufferedReader reader = new BufferedReader(
new InputStreamReader(file.getInputStream())
);
// 统计总行数(模拟总数据量)
long totalLines = reader.lines().count();
reader.close();
// 重新读取,逐行处理
BufferedReader processReader = new BufferedReader(
new InputStreamReader(file.getInputStream())
);
long current = 0;
String line;
while ((line = processReader.readLine()) != null) {
current++;
// 计算进度:保留整数百分比
int progress = (int) ((current * 100) / totalLines);
// ✅ 正确方法名
importProgressCache.setProgress(taskId, progress);
// 模拟业务处理(可替换为入库逻辑)
Thread.sleep(50);
}
processReader.close();
// 完成 100% ✅ 正确方法名
importProgressCache.setProgress(taskId, 100);
} catch (Exception e) {
// -1 表示失败
importProgressCache.setProgress(taskId, -1);
}
}).start();
return Result.success("导入任务已开始,taskId:" + taskId);
}
/**
* 2. 查询导入进度接口
*/
@GetMapping("/progress/{taskId}")
public Result<Integer> getProgress(@PathVariable String taskId) {
Integer progress = importProgressCache.getProgress(taskId);
return Result.progress(progress);
}
}