如何通过Spring Rest获取二进制数据与JSON?求代码示例
用Spring Rest同时获取二进制数据与JSON的两种方案
没问题!我来给你分享两种实用的实现方式,帮你在Spring Rest接口里同时拿到二进制文件(比如PDF、图片)和附加的JSON信息~
方案一:响应头携带JSON元数据,响应体返回二进制数据
这种方式比较轻量,适合元数据内容不多的场景。咱们把JSON格式的附加信息放在HTTP响应头里,响应体直接返回二进制文件内容。
服务器端代码示例
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.Map; @RestController public class FileWithMetaController { private final ObjectMapper objectMapper = new ObjectMapper(); @GetMapping("/download-with-meta") public ResponseEntity<Resource> downloadFileWithMetadata() throws Exception { // 1. 准备二进制文件(这里用classpath下的PDF为例) Resource pdfFile = new ClassPathResource("sample.pdf"); // 2. 准备附加的JSON元数据 Map<String, Object> metaData = new HashMap<>(); metaData.put("fileId", "12345"); metaData.put("fileName", "sample.pdf"); metaData.put("fileSize", pdfFile.contentLength()); metaData.put("description", "这是一个示例PDF文件"); // 3. 把元数据转成JSON字符串,放进响应头 String metaJson = objectMapper.writeValueAsString(metaData); HttpHeaders headers = new HttpHeaders(); headers.add("X-File-Metadata", metaJson); headers.setContentType(MediaType.APPLICATION_PDF); headers.setContentDispositionFormData("attachment", pdfFile.getFilename()); // 4. 返回响应 return new ResponseEntity<>(pdfFile, headers, HttpStatus.OK); } }
客户端代码示例(用RestTemplate)
import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Map; public class FileClient { public static void main(String[] args) throws Exception { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/download-with-meta"; ResponseEntity<Resource> response = restTemplate.exchange( url, HttpMethod.GET, null, Resource.class ); // 1. 从响应头获取JSON元数据并解析 String metaJson = response.getHeaders().getFirst("X-File-Metadata"); ObjectMapper objectMapper = new ObjectMapper(); Map<String, Object> metaData = objectMapper.readValue(metaJson, Map.class); System.out.println("文件元数据:" + metaData); // 2. 获取二进制文件内容(这里可以保存到本地或者直接处理) Resource fileResource = response.getBody(); if (fileResource != null) { // 示例:保存到本地 // Files.copy(fileResource.getInputStream(), Paths.get("downloaded_sample.pdf")); System.out.println("文件内容已获取,长度:" + fileResource.contentLength()); } } }
方案二:Multipart响应,拆分二进制与JSON为不同Part
如果你的元数据比较复杂,或者更倾向于规范的多部分响应格式,可以用multipart/form-data类型,把二进制文件和JSON分别作为响应的两个Part。
服务器端代码示例
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @RestController public class MultipartFileController { @GetMapping(value = "/download-multipart", produces = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity<MultiValueMap<String, Object>> downloadMultipart() { // 1. 准备二进制文件 Resource pdfFile = new ClassPathResource("sample.pdf"); // 2. 准备JSON元数据 Map<String, Object> metaData = new HashMap<>(); metaData.put("fileId", "67890"); metaData.put("fileName", "sample_multipart.pdf"); metaData.put("author", "StackExchange User"); // 3. 构建Multipart响应体 MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); // 添加文件Part HttpHeaders fileHeaders = new HttpHeaders(); fileHeaders.setContentType(MediaType.APPLICATION_PDF); body.add("file", new ResponseEntity<>(pdfFile, fileHeaders, HttpStatus.OK)); // 添加元数据Part HttpHeaders metaHeaders = new HttpHeaders(); metaHeaders.setContentType(MediaType.APPLICATION_JSON); body.add("metadata", new ResponseEntity<>(metaData, metaHeaders, HttpStatus.OK)); // 4. 返回响应 return new ResponseEntity<>(body, HttpStatus.OK); } }
客户端代码示例(用RestTemplate)
import org.springframework.core.io.Resource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Map; public class MultipartFileClient { public static void main(String[] args) throws Exception { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/download-multipart"; ResponseEntity<MultiValueMap<String, Object>> response = restTemplate.exchange( url, HttpMethod.GET, null, (Class<MultiValueMap<String, Object>>) (Class<?>) MultiValueMap.class ); MultiValueMap<String, Object> body = response.getBody(); if (body != null) { // 1. 解析元数据Part ResponseEntity<Map> metaResponse = (ResponseEntity<Map>) body.getFirst("metadata"); Map<String, Object> metaData = metaResponse.getBody(); System.out.println("Multipart元数据:" + metaData); // 2. 解析文件Part ResponseEntity<Resource> fileResponse = (ResponseEntity<Resource>) body.getFirst("file"); Resource fileResource = fileResponse.getBody(); if (fileResource != null) { System.out.println("Multipart文件长度:" + fileResource.contentLength()); // 保存文件逻辑... } } } }
小提醒
- 方案一中,如果JSON元数据包含特殊字符,建议对JSON字符串做Base64编码后再放入响应头,避免解析异常。
- 方案二中,确保客户端和服务器端都正确处理
multipart/form-data类型的响应,RestTemplate默认支持这种类型的解析。
内容的提问来源于stack exchange,提问作者user3593086
相关产品推荐
相关产品推荐

