diff --git a/src/main/java/com/sztzjy/financial_bigdata/controller/stu/JupyterController.java b/src/main/java/com/sztzjy/financial_bigdata/controller/stu/JupyterController.java new file mode 100644 index 0000000..7773d09 --- /dev/null +++ b/src/main/java/com/sztzjy/financial_bigdata/controller/stu/JupyterController.java @@ -0,0 +1,252 @@ +package com.sztzjy.financial_bigdata.controller.stu; + +import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSONObject; +import com.sztzjy.financial_bigdata.annotation.AnonymousAccess; +import com.sztzjy.financial_bigdata.util.ResultEntity; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @author 17803 + * @date 2024-07-22 17:31 + */ + +@RestController +@Api(tags = "jupyter运行python代码") +@RequestMapping("/api/jupyter") +public class JupyterController { + @ApiOperation("文件校验") + @PostMapping("/validate") + @AnonymousAccess + public ResultEntity getBlockResources(@RequestBody JSONObject upCodeJson) { + + //虚拟空间路径 + String pyPath = "/usr/local/tianzeProject/py/"; + + System.out.println(upCodeJson); + String pythonCodeUp = upCodeJson.getString("code"); + String pythonCode = ""; + + if (pythonCodeUp.contains("/dataResource")) { + pythonCode = pythonCodeUp.replace("/dataResource", pyPath + "dataResource"); + } else { + pythonCode = pythonCodeUp; + } + if (pythonCode.contains("show")) { + return validatePythonCodePhoto(upCodeJson); + } + try { + + String s = IdUtil.simpleUUID(); + // 写入临时Python文件 + String tempPythonFile = "/usr/local/tianzeProject/py/code/" + s + ".py"; + + try (PrintWriter out = new PrintWriter(tempPythonFile)) { + out.println(pythonCode); + } + + + String[] command = {"docker", "exec", "pyexe", "python", tempPythonFile}; + // 创建一个新的进程来执行Python代码 + Process process = Runtime.getRuntime().exec(command); + + // 获取进程的输入流 + BufferedReader inputStream = new BufferedReader(new InputStreamReader(process.getInputStream())); + + // 获取进程的输出流 + BufferedReader errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream())); + +// // 向进程的输入流写入Python代码 +// process.getOutputStream().write(pythonCode.getBytes()); +// process.getOutputStream().flush(); +// process.getOutputStream().close(); + + // 读取Python代码的输出 + String line; + StringBuilder output = new StringBuilder(); + while ((line = inputStream.readLine()) != null) { + output.append(line).append("\n"); + } + + // 读取Python代码的错误信息 + StringBuilder errors = new StringBuilder(); + while ((line = errorStream.readLine()) != null) { + errors.append(line).append("\n"); + } + + // 等待进程执行完成 + int exitCode = process.waitFor(); + + if (exitCode == 0) { + // 执行成功,输出Python代码的结果 + System.out.println("Python code output:\n" + output.toString()); + return new ResultEntity(HttpStatus.OK, output.toString()); + } else { + // 执行失败,输出错误信息 + System.err.println("Error executing Python code:\n" + errors.toString()); + return new ResultEntity(HttpStatus.OK, errors.toString()); + } + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + return new ResultEntity<>(HttpStatus.BAD_REQUEST); + } + + + @PostMapping("/validatePythonCodeImg") + @ApiOperation("代码检验图片") + @AnonymousAccess + public ResultEntity validatePythonCodePhoto(@RequestBody JSONObject upCodeJson) { + + + System.out.println(upCodeJson); + String pythonCode = upCodeJson.getString("code"); + + String s = IdUtil.simpleUUID(); + List stringList = new ArrayList<>(); + + try { + String pyCode = "/usr/local/tianzeProject/py/code/"; + String pyPath = "/usr/local/tianzeProject/py/img/"; + + // 写入临时Python文件 + String tempPythonFile = pyCode + s + ".py"; + + // 输出流示例 + PrintWriter out = null; + + //============ + if (pythonCode.contains("show")) { + // 将 pythonCode 按行拆分 + String[] lines = pythonCode.split("\\r?\\n"); + out = new PrintWriter(tempPythonFile); + int length = lines.length; + + for (int i = 0; i < lines.length; i++) { + + String imgPathv = IdUtil.simpleUUID(); + String plotFile = pyPath + imgPathv + ".png"; + + // 处理最后一行的情况,确保不重复插入 plt.savefig() + if (i == length - 1 && lines[i].contains("plt.show()")) { + out.println("plt.savefig('" + plotFile + "')"); + out.println(lines[i]); + + System.out.println("最后一次执行"+i); + stringList.add(pyPath + imgPathv + ".png"); + System.out.println("保存图片路径:" + pyPath + imgPathv + ".png"); + System.out.println("最后一行添加"+lines[i]); + continue; + } + + lines[i] = lines[i].trim(); + + // 判断是否为 plt.show() 相关的语句 + if (lines[i].contains("plt.show()")&&i != length - 1) { + + out.println("plt.savefig('" + plotFile + "')"); + stringList.add(pyPath + imgPathv + ".png"); + System.out.println("保存图片路径:" + pyPath + imgPathv + ".png"); + } + + // 在 plt.savefig() 之后输出原来的 plt.show() 语句 + out.println(lines[i]); + } + System.out.println("数据写入完成:"+stringList); + + out.close(); + } + + String[] command = {"docker", "exec", "pyexe", "python", pyCode + s + ".py"}; + // 创建一个新的进程来执行Python代码 + Process process = Runtime.getRuntime().exec(command); + + // 获取进程的输入流 + BufferedReader inputStream = new BufferedReader(new InputStreamReader(process.getInputStream())); + + // 获取进程的输出流 + BufferedReader errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream())); + + // 向进程的输入流写入Python代码 + process.getOutputStream().write(pythonCode.getBytes()); + process.getOutputStream().flush(); + process.getOutputStream().close(); + + // 读取Python代码的输出 + String line; + StringBuilder output = new StringBuilder(); + while ((line = inputStream.readLine()) != null) { + output.append(line).append("\n"); + } + + // 读取Python代码的错误信息 + StringBuilder errors = new StringBuilder(); + while ((line = errorStream.readLine()) != null) { + errors.append(line).append("\n"); + } + + // 等待进程执行完成 + int exitCode = process.waitFor(); + System.out.println("代码运行结束!!"); + if (exitCode == 0) { + // 执行成功,输出Python代码的结果 + System.out.println("Python code output:\n" + output.toString()); + + + String base64Image = ""; + List base64ImageList = new ArrayList<>(); + + if (!stringList.isEmpty()) { + + for (int i = 0; i < stringList.size(); i++) { + // 读取图片文件并转换为Base64字符串 + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + System.out.println("读取的stringList文件:" + stringList.get(i)); + + try (FileInputStream fis = new FileInputStream(stringList.get(i))) { + byte[] buffer = new byte[1024]; + int len; + while ((len = fis.read(buffer)) != -1) { + baos.write(buffer, 0, len); + } + System.out.println("图片读取成功!!!!"); + } + base64Image = Base64.encodeBase64String(baos.toByteArray()); + base64ImageList.add(base64Image); + } + + return new ResultEntity(HttpStatus.OK, output.toString(), base64ImageList); + } else { + return new ResultEntity(HttpStatus.OK, output.toString()); + } + + + }else { + // 执行失败,输出错误信息 + System.err.println("Error executing Python code:\n" + errors.toString()); + return new ResultEntity(HttpStatus.OK, errors.toString()); + } + + + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + return new ResultEntity(HttpStatus.BAD_REQUEST, e); + } + + } + + + + +} \ No newline at end of file