You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:21:18