package com.example.compileproxyserver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.stream.Collectors; @RestController public class FileUploadController { private static final String UPLOAD_DIR = "/home/devicemanager/programs"; private static final String TARGET_FILE = "radarcal.cc"; private static final String USER_NAME = "cdProxy"; private static final String USER_PASSWORD = "cdProxy_zed"; @Autowired private JwtUtil jwtUtil; @PostMapping("/login") public ResponseEntity login(@RequestParam("username") String username, @RequestParam("password") String password) { System.out.println("username: " + username + " password: " + password); if (USER_NAME.equals(username) && USER_PASSWORD.equals(password)) { String token = new JwtUtil().generateToken(username); //test System.out.println("token: " + token + " username: " + username + " password: " + password + "extractname: " + jwtUtil.extractUsername(token)); return ResponseEntity.ok(new JwtUtil.AuthResponse(token).getToken()); } else { return ResponseEntity.status(401).body("Invalid username or password"); } } @PostMapping("/upload") public ResponseEntity uploadFile(@RequestHeader("Authorization") String authorizationHeader, @RequestParam("file") MultipartFile file) { try { String token = authorizationHeader.replace("Bearer ", ""); System.out.println("token: " + token + " username: " + "extractname: " + jwtUtil.extractUsername(token)); String username = jwtUtil.extractUsername(token); if(jwtUtil.validateToken(token, username)){ System.out.println("Token is valid"); return ResponseEntity.status(401).body("token错误,请刷新页面重新登录"); } // 创建上传目录 File uploadDir = new File(UPLOAD_DIR); if (!uploadDir.exists()) { uploadDir.mkdirs(); } System.out.println("upload file: " + file.getOriginalFilename()); // 保存上传的文件 Path targetFilePath = Paths.get(UPLOAD_DIR, TARGET_FILE); File tempFile = File.createTempFile("temp-", ".cs"); file.transferTo(tempFile); // 移动文件并替换已存在的文件 Files.move(tempFile.toPath(), targetFilePath, StandardCopyOption.REPLACE_EXISTING); // 调用编译类进行编译 PublishResult result = publishProject(Paths.get(UPLOAD_DIR).getParent()); if (result.isSuccess()) { // 找到发布后的 radarcal 文件 Path publishedFilePath = findPublishedFile(result.getPublishDirectory()); if (publishedFilePath != null) { // 返回发布后的文件 Resource resource = new FileSystemResource(publishedFilePath.toFile()); HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=radarcal"); return ResponseEntity.ok() .headers(headers) .contentLength(resource.contentLength()) .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(resource); } } // 编译失败,返回错误日志 return ResponseEntity.status(500) .contentType(MediaType.TEXT_PLAIN) .body(result.getErrorLog()); } catch (IOException | InterruptedException e) { e.printStackTrace(); return ResponseEntity.status(500) .contentType(MediaType.TEXT_PLAIN) .body(e.getMessage()); } catch (RuntimeException e) { return ResponseEntity.status(401).body(e.getMessage()); } } private PublishResult publishProject(Path projectDir) throws IOException, InterruptedException { // 定义发布目录 Path publishDir = projectDir.resolve("build"); System.out.println("publishDir: " + publishDir); // 执行 rm -rf build && mkdir build ProcessBuilder rmMkdirBuilder = new ProcessBuilder("bash", "-c", "rm -rf build && mkdir build"); rmMkdirBuilder.directory(projectDir.toFile()); Process rmMkdirProcess = rmMkdirBuilder.start(); int rmMkdirExitCode = rmMkdirProcess.waitFor(); if (rmMkdirExitCode != 0) { // 获取错误流并读取错误信息 try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(rmMkdirProcess.getErrorStream()))) { String errorLog = errorReader.lines().collect(Collectors.joining("\n")); System.out.println("Failed to clean and create build directory: " + errorLog); return new PublishResult(false, "Failed to clean and create build directory: " + errorLog, publishDir); } } // 执行 cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=arm-toolchain.cmake && make -j && cd .. ProcessBuilder cmakeMakeBuilder = new ProcessBuilder("bash", "-c", "cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=arm-toolchain.cmake && make -j && cd .."); cmakeMakeBuilder.directory(projectDir.toFile()); Process cmakeMakeProcess = cmakeMakeBuilder.start(); int cmakeMakeExitCode = cmakeMakeProcess.waitFor(); if (cmakeMakeExitCode != 0) { // 获取错误流并读取错误信息 try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(cmakeMakeProcess.getErrorStream()))) { String errorLog = errorReader.lines().collect(Collectors.joining("\n")); return new PublishResult(false, "CMake or Make failed: " + " Error: " + errorLog, publishDir); } } return new PublishResult(true, "Build succeeded", publishDir); } private Path findPublishedFile(Path publishDir) { File[] files = publishDir.toFile().listFiles(); if (files != null) { for (File file : files) { if (file.isFile() && file.getName().equals("radarcal")) { return file.toPath(); } } } return null; } private static class PublishResult { private final boolean success; private final String errorLog; private final Path publishDirectory; public PublishResult(boolean success, String errorLog, Path publishDirectory) { this.success = success; this.errorLog = errorLog; this.publishDirectory = publishDirectory; } public boolean isSuccess() { return success; } public String getErrorLog() { return errorLog; } public Path getPublishDirectory() { return publishDirectory; } } }