如何使用OkHttp发送包含JSON数据与图片文件的Multipart POST请求
解决同时发送JSON数据与图片文件的POST请求问题
这个问题我之前也碰到过,核心原因是你混淆了两种不同的HTTP请求内容类型——单独发JSON用的是application/json,发文件用的是multipart/form-data,同时发送时必须统一用multipart/form-data格式,把JSON数据作为一个表单字段来传递,而不是单独用JSON请求体。
下面我给你几种常见Java HTTP客户端的实现方案:
方案1:使用OkHttp(推荐,简洁易用)
OkHttp对multipart请求的支持非常友好,直接通过MultipartBody.Builder构建请求体即可:
import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import org.json.JSONArray; import org.json.JSONObject; import java.io.File; import java.io.IOException; public class MultipartRequestExample { public static void main(String[] args) throws IOException { // 1. 构建JSON数据并转成字符串 JSONObject jsonParam = new JSONObject(); jsonParam.put("title", "XYZ"); jsonParam.put("isGroup", "true"); jsonParam.put("ownerId", "123"); JSONArray jsonArray = new JSONArray(); jsonArray.put("example_item_1"); // 替换成你的实际数组内容 jsonParam.put("your_array_key", jsonArray); // 替换成你的数组字段名 // 2. 初始化OkHttpClient OkHttpClient client = new OkHttpClient(); // 3. 构建Multipart请求体 File imageFile = new File("/path/to/your/image.jpg"); // 替换成你的图片路径 RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) // 添加JSON字段,注意这里把JSON转成字符串,字段名和后端约定好 .addFormDataPart("jsonData", jsonParam.toString()) // 添加图片文件,第三个参数是文件名,第四个是文件MediaType .addFormDataPart("image", imageFile.getName(), RequestBody.create(MediaType.parse("image/jpeg"), imageFile)) .build(); // 4. 发送请求 Request request = new Request.Builder() .url("https://your-api-endpoint.com/upload") // 替换成你的接口地址 .post(requestBody) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string()); } } }
方案2:使用Spring RestTemplate(如果是Spring项目)
如果你的项目是Spring Boot或Spring MVC,可以用RestTemplate来实现:
import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import org.json.JSONArray; import org.json.JSONObject; import java.io.File; public class SpringMultipartExample { public static void main(String[] args) { // 1. 构建JSON数据并转成字符串 JSONObject jsonParam = new JSONObject(); jsonParam.put("title", "XYZ"); jsonParam.put("isGroup", "true"); jsonParam.put("ownerId", "123"); JSONArray jsonArray = new JSONArray(); jsonArray.put("example_item_1"); jsonParam.put("your_array_key", jsonArray); // 2. 构建Multipart参数 MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); body.add("jsonData", jsonParam.toString()); // JSON字符串字段 File imageFile = new File("/path/to/your/image.jpg"); body.add("image", new FileSystemResource(imageFile)); // 图片文件 // 3. 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); // 4. 发送请求 RestTemplate restTemplate = new RestTemplate(); HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers); ResponseEntity<String> response = restTemplate.postForEntity( "https://your-api-endpoint.com/upload", requestEntity, String.class ); System.out.println(response.getBody()); } }
方案3:原生HttpURLConnection(不推荐,代码繁琐,但无需第三方依赖)
如果不想引入第三方库,可以用原生的HttpURLConnection手动构建multipart请求:
import org.json.JSONArray; import org.json.JSONObject; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.UUID; public class NativeMultipartExample { public static void main(String[] args) throws IOException { String boundary = UUID.randomUUID().toString(); URL url = new URL("https://your-api-endpoint.com/upload"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); // 构建JSON数据 JSONObject jsonParam = new JSONObject(); jsonParam.put("title", "XYZ"); jsonParam.put("isGroup", "true"); jsonParam.put("ownerId", "123"); JSONArray jsonArray = new JSONArray(); jsonArray.put("example_item_1"); jsonParam.put("your_array_key", jsonArray); try (OutputStream os = conn.getOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8), true)) { // 添加JSON字段 writer.append("--").append(boundary).append("\r\n"); writer.append("Content-Disposition: form-data; name=\"jsonData\"").append("\r\n"); writer.append("Content-Type: application/json; charset=UTF-8").append("\r\n"); writer.append("\r\n"); writer.append(jsonParam.toString()).append("\r\n"); // 添加图片文件 writer.append("--").append(boundary).append("\r\n"); writer.append("Content-Disposition: form-data; name=\"image\"; filename=\"image.jpg\"").append("\r\n"); writer.append("Content-Type: image/jpeg").append("\r\n"); writer.append("\r\n"); writer.flush(); File imageFile = new File("/path/to/your/image.jpg"); try (FileInputStream fis = new FileInputStream(imageFile)) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } os.flush(); } // 结束边界 writer.append("\r\n").flush(); writer.append("--").append(boundary).append("--").append("\r\n").flush(); } // 获取响应 int responseCode = conn.getResponseCode(); System.out.println("Response Code: " + responseCode); try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) { String line; StringBuilder response = new StringBuilder(); while ((line = br.readLine()) != null) { response.append(line); } System.out.println(response.toString()); } conn.disconnect(); } }
后端接收注意事项
确保你的后端接口能正确解析multipart/form-data中的字段:
- 比如在Spring Boot中,你可以这样接收:
@PostMapping("/upload") public ResponseEntity<String> handleUpload( @RequestParam("jsonData") String jsonData, @RequestParam("image") MultipartFile image) { // 把jsonData转成你的实体类,比如用ObjectMapper YourEntity entity = new ObjectMapper().readValue(jsonData, YourEntity.class); // 处理图片文件 // ... return ResponseEntity.ok("Success"); }
另外要注意几个坑:
- 确保JSON字符串序列化正确,没有语法错误
- 图片文件路径正确,文件可读
- 后端接口的字段名和你请求中的字段名完全一致(比如
jsonData、image) - 如果是大文件,要配置后端的multipart文件大小限制
内容的提问来源于stack exchange,提问作者Prithniraj Nicyone
相关产品推荐
相关产品推荐

