Spring Boot中如何通过RestTemplate或WebClient获取二进制文件数据
问题原因与修复方案
- 核心问题1:请求映射方法访问修饰符错误
你当前的receiveFile方法是private修饰的,Spring MVC要求被@RequestMapping注解标注的请求处理方法必须为public修饰,否则Spring无法正确代理调用该方法,最终返回的二进制内容大概率是框架层的错误响应内容,而非正常的PDF文件流。 - 问题2:缺少明确的Accept请求头
你注释了设置Accept头的代码,虽然直接调用下游接口能返回PDF,但通过WebClient调用时最好显式指定接受的媒体类型为application/pdf,避免下游接口根据默认Accept头返回其他格式的错误响应(比如JSON格式的报错信息),导致拿到的字节数组本身就不是PDF内容。 - 问题3:未显式校验下游响应状态
当前代码没有对下游接口的响应状态做校验,如果下游返回4xx/5xx错误,retrieve()方法默认会抛出异常,若全局异常处理返回了其他内容,也会导致最终返回的字节流不是PDF。 - 优化点:可显式设置返回给请求方的下载相关头
如果下游接口没有返回正确的Content-Disposition头,你可以手动添加该头,确保Postman识别为可下载的PDF文件。
修复后参考代码
// 方法改为public修饰 @RequestMapping(value="/getDocument", method=RequestMethod.POST) public ResponseEntity<byte[]> receiveFile() throws URISyntaxException { MultiValueMap<String, String> map = new LinkedMultiValueMap<>(); map.add("mobile","XXXXXXXXX9"); WebClient webClient = WebClient.create(); ResponseEntity<byte[]> apiResponse = webClient.post() .uri(new URI("https://api.myapp.net.in/getDocument")) .header("username", "xyz") .contentType(MediaType.APPLICATION_FORM_URLENCODED) // 放开Accept头配置,明确要求下游返回PDF .accept(MediaType.APPLICATION_PDF) .body(BodyInserters.fromFormData(map)) .retrieve() // 可选:添加非2xx状态的异常处理逻辑,避免返回错误内容 .onStatus(HttpStatusCode::isError, clientResponse -> clientResponse.bodyToMono(String.class) .map(body -> new RuntimeException("下游接口调用失败:" + body)) ) .toEntity(byte[].class) .block(); // 可选:如果下游没有返回正确的头,手动设置响应头 return ResponseEntity.ok() .contentType(MediaType.APPLICATION_PDF) // 可根据实际需求修改文件名 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"document.pdf\"") .body(apiResponse.getBody()); }
内容的提问来源于stack exchange,提问作者Lalitkumar.annaldas
相关产品推荐
相关产品推荐

