咨询Spring Boot应用间文件上传通信方案:AngularApp传文件至batchApp
当然可以用REST API实现这个跨应用的文件传递!这是最贴合Spring Boot生态的方案,我给你分两种场景拆解具体实现步骤:
方案一:直接转发MultipartFile(适合小文件)
这种方式是把AngularApp收到的MultipartFile直接通过REST请求转发给batchApp,逻辑简单直接。
步骤1:在batchApp中编写文件接收接口
先给batchApp添加一个接收文件的POST接口,用来接收AngularApp转发过来的文件:
@RestController @RequestMapping("/batch") public class BatchFileController { @PostMapping("/upload") // 允许AngularApp跨域访问,根据实际情况调整origins参数 @CrossOrigin(origins = "http://localhost:8870") public ResponseEntity<String> receiveFile(@RequestParam("file") MultipartFile file) { // 这里可以根据需求处理文件:保存到本地目录/直接传入批处理任务 try { Files.copy(file.getInputStream(), Paths.get("batch-upload-dir", file.getOriginalFilename()), StandardCopyOption.REPLACE_EXISTING); return ResponseEntity.ok("文件已成功接收:" + file.getOriginalFilename()); } catch (IOException e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("接收文件失败:" + e.getMessage()); } } }
步骤2:在AngularApp中添加调用batchApp的逻辑
AngularApp已经能接收前端文件,现在只需要用Spring的WebClient(Spring 5+推荐的非阻塞客户端)来调用batchApp的接口。
首先在AngularApp中配置WebClient:
@Configuration public class WebClientConfig { @Bean public WebClient batchWebClient() { return WebClient.builder() .baseUrl("http://localhost:8871") // batchApp的基础地址 .build(); } }
然后修改AngularApp的文件上传控制器,在保存本地文件后,转发文件到batchApp:
@RestController public class AngularFileController { private final WebClient batchWebClient; // 构造注入WebClient public AngularFileController(WebClient batchWebClient) { this.batchWebClient = batchWebClient; } @PostMapping("/post") public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) { // 1. 先执行你已实现的本地保存逻辑 try { Files.copy(file.getInputStream(), Paths.get("upload-dir", file.getOriginalFilename()), StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("保存文件到本地失败:" + e.getMessage()); } // 2. 转发文件到batchApp try { String batchResponse = batchWebClient.post() .uri("/batch/upload") .contentType(MediaType.MULTIPART_FORM_DATA) .body(BodyInserters.fromMultipartData("file", new ByteArrayResource(file.getBytes()) { @Override public String getFilename() { return file.getOriginalFilename(); // 必须指定文件名,否则batchApp无法识别 } })) .retrieve() .bodyToMono(String.class) .block(); // 异步场景可去掉block,改用Mono/Flux返回 return ResponseEntity.ok("文件上传到AngularApp成功,且已转发到batchApp:" + batchResponse); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("转发文件到batchApp失败:" + e.getMessage()); } } }
方案二:传递文件路径(适合大文件,避免内存占用)
如果文件体积较大,直接转发MultipartFile会占用过多内存,这时候可以让AngularApp保存文件后,把文件路径传给batchApp,由batchApp直接读取文件(前提是两个应用能访问到同一个文件目录,比如共享磁盘、NFS,或者用对象存储如MinIO传递文件URL)。
步骤1:batchApp添加接收文件路径的接口
@RestController @RequestMapping("/batch") public class BatchFileController { @PostMapping("/upload-by-path") @CrossOrigin(origins = "http://localhost:8870") public ResponseEntity<String> receiveFileByPath(@RequestParam("filePath") String filePath) { File targetFile = new File(filePath); if (!targetFile.exists()) { return ResponseEntity.badRequest().body("文件不存在:" + filePath); } // 读取文件并处理批任务 try { Files.copy(targetFile.toPath(), Paths.get("batch-upload-dir", targetFile.getName()), StandardCopyOption.REPLACE_EXISTING); return ResponseEntity.ok("通过路径读取文件成功:" + targetFile.getName()); } catch (IOException e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("处理文件失败:" + e.getMessage()); } } }
步骤2:AngularApp修改控制器传递路径
@PostMapping("/post") public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) { String localFilePath = "upload-dir/" + file.getOriginalFilename(); // 1. 保存文件到本地 try { Files.copy(file.getInputStream(), Paths.get(localFilePath), StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("保存文件到本地失败:" + e.getMessage()); } // 2. 传递文件路径给batchApp try { String batchResponse = batchWebClient.post() .uri(uriBuilder -> uriBuilder.path("/batch/upload-by-path") .queryParam("filePath", localFilePath) .build()) .retrieve() .bodyToMono(String.class) .block(); return ResponseEntity.ok("文件上传成功,已通知batchApp读取文件:" + batchResponse); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("通知batchApp失败:" + e.getMessage()); } }
关键注意事项
- 跨域配置:如果两个应用端口不同,必须在batchApp的控制器上添加
@CrossOrigin注解,或者全局配置跨域规则,避免请求被浏览器拦截。 - 文件大小限制:Spring Boot默认限制Multipart文件大小,需要在两个应用的
application.properties中配置:spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-request-size=100MB - 异步处理:如果批处理任务耗时较长,建议batchApp用
@Async或者Spring Batch的JobLauncher异步执行任务,避免AngularApp的请求超时。
内容的提问来源于stack exchange,提问作者Logan Wlv
相关产品推荐
相关产品推荐

