Http post 发送 multipart/form-data 格式数据-Java 实现

Http post 发送 multipart/form-data 格式数据-Java 实现

  • 代码
  • 参考博客

代码

package awesome.data.structure.http;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * http 工具类
 *
 * @author: Andy
 * @time: 2019/7/9 17:09
 * @since
 */
public class HttpUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
    /**
     * multipart/form-data 格式发送数据时各个部分分隔符的前缀,必须为 --
     */
    private static final String BOUNDARY_PREFIX = "--";
    /**
     * 回车换行,用于一行的结尾
     */
    private static final String LINE_END = "\r\n";

    /**
     * post 请求:以表单方式提交数据
     * 

* 由于 multipart/form-data 不是 http 标准内容,而是属于扩展类型, * 因此需要自己构造数据结构,具体如下: *

* 1、首先,设置 Content-Type *

* Content-Type: multipart/form-data; boundary=${bound} *

* 其中${bound} 是一个占位符,代表我们规定的分割符,可以自己任意规定, * 但为了避免和正常文本重复了,尽量要使用复杂一点的内容 *

* 2、设置主体内容 *

* --${bound} * Content-Disposition: form-data; name="userName" *

* Andy * --${bound} * Content-Disposition: form-data; name="file"; filename="测试.excel" * Content-Type: application/octet-stream *

* 文件内容 * --${bound}-- *

* 其中${bound}是之前头信息中的分隔符,如果头信息中规定是123,那这里也要是123; * 可以很容易看到,这个请求提是多个相同部分组成的: * 每一部分都是以--加分隔符开始的,然后是该部分内容的描述信息,然后一个回车换行,然后是描述信息的具体内容; * 如果传送的内容是一个文件的话,那么还会包含文件名信息以及文件内容类型。 * 上面第二部分是一个文件体的结构,最后以--分隔符--结尾,表示请求体结束 * * @param urlStr 请求的url * @param filePathMap key 参数名,value 文件的路径 * @param keyValues 普通参数的键值对 * @param headers * @return * @throws IOException */ public static HttpResponse postFormData(String urlStr, Map<String, String> filePathMap, Map<String, Object> keyValues, Map<String, Object> headers) throws IOException { HttpResponse response; HttpURLConnection conn = getHttpURLConnection(urlStr, headers); //分隔符,可以任意设置,这里设置为 MyBoundary+ 时间戳(尽量复杂点,避免和正文重复) String boundary = "MyBoundary" + System.currentTimeMillis(); //设置 Content-Type 为 multipart/form-data; boundary=${boundary} conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); //发送参数数据 try (DataOutputStream out = new DataOutputStream(conn.getOutputStream())) { //发送普通参数 if (keyValues != null && !keyValues.isEmpty()) { for (Map.Entry<String, Object> entry : keyValues.entrySet()) { writeSimpleFormField(boundary, out, entry); } } //发送文件类型参数 if (filePathMap != null && !filePathMap.isEmpty()) { for (Map.Entry<String, String> filePath : filePathMap.entrySet()) { writeFile(filePath.getKey(), filePath.getValue(), boundary, out); } } //写结尾的分隔符--${boundary}--,然后回车换行 String endStr = BOUNDARY_PREFIX + boundary + BOUNDARY_PREFIX + LINE_END; out.write(endStr.getBytes()); } catch (Exception e) { LOGGER.error("HttpUtils.postFormData 请求异常!", e); response = new HttpResponse(500, e.getMessage()); return response; } return getHttpResponse(conn); } /** * 获得连接对象 * * @param urlStr * @param headers * @return * @throws IOException */ private static HttpURLConnection getHttpURLConnection(String urlStr, Map<String, Object> headers) throws IOException { URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置超时时间 conn.setConnectTimeout(50000); conn.setReadTimeout(50000); //允许输入流 conn.setDoInput(true); //允许输出流 conn.setDoOutput(true); //不允许使用缓存 conn.setUseCaches(false); //请求方式 conn.setRequestMethod("POST"); //设置编码 utf-8 conn.setRequestProperty("Charset", "UTF-8"); //设置为长连接 conn.setRequestProperty("connection", "keep-alive"); //设置其他自定义 headers if (headers != null && !headers.isEmpty()) { for (Map.Entry<String, Object> header : headers.entrySet()) { conn.setRequestProperty(header.getKey(), header.getValue().toString()); } } return conn; } private static HttpResponse getHttpResponse(HttpURLConnection conn) { HttpResponse response; try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) { int responseCode = conn.getResponseCode(); StringBuilder responseContent = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { responseContent.append(line); } response = new HttpResponse(responseCode, responseContent.toString()); } catch (Exception e) { LOGGER.error("获取 HTTP 响应异常!", e); response = new HttpResponse(500, e.getMessage()); } return response; } /** * 写文件类型的表单参数 * * @param paramName 参数名 * @param filePath 文件路径 * @param boundary 分隔符 * @param out * @throws IOException */ private static void writeFile(String paramName, String filePath, String boundary, DataOutputStream out) { try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) { /** * 写分隔符--${boundary},并回车换行 */ String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END; out.write(boundaryStr.getBytes()); /** * 写描述信息(文件名设置为上传文件的文件名): * 写 Content-Disposition: form-data; name="参数名"; filename="文件名",并回车换行 * 写 Content-Type: application/octet-stream,并两个回车换行 */ String fileName = new File(filePath).getName(); String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", paramName, fileName) + LINE_END; out.write(contentDispositionStr.getBytes()); String contentType = "Content-Type: application/octet-stream" + LINE_END + LINE_END; out.write(contentType.getBytes()); String line; while ((line = fileReader.readLine()) != null) { out.write(line.getBytes()); } //回车换行 out.write(LINE_END.getBytes()); } catch (Exception e) { LOGGER.error("写文件类型的表单参数异常", e); } } /** * 写普通的表单参数 * * @param boundary 分隔符 * @param out * @param entry 参数的键值对 * @throws IOException */ private static void writeSimpleFormField(String boundary, DataOutputStream out, Map.Entry<String, Object> entry) throws IOException { //写分隔符--${boundary},并回车换行 String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END; out.write(boundaryStr.getBytes()); //写描述信息:Content-Disposition: form-data; name="参数名",并两个回车换行 String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"", entry.getKey()) + LINE_END + LINE_END; out.write(contentDispositionStr.getBytes()); //写具体内容:参数值,并回车换行 String valueStr = entry.getValue().toString() + LINE_END; out.write(valueStr.getBytes()); } public static void main(String[] args) throws IOException { //请求 url String url = "http://127.0.0.1:8080/settlement/createTaskSettlement"; // keyValues 保存普通参数 Map<String, Object> keyValues = new HashMap<>(); String taskDescription = "众包测试"; String taskExpiredTime = "2019-09-12"; String taskRequirement = "1"; String taskTitle = "测试测试啊"; keyValues.put("task_description", taskDescription); keyValues.put("task_expired_time", taskExpiredTime); keyValues.put("task_requirement", taskRequirement); keyValues.put("task_title", taskTitle); // filePathMap 保存文件类型的参数名和文件路径 Map<String, String> filePathMap = new HashMap<>(); String paramName = "file"; String filePath = "C:\\Users\\magos\\Downloads\\Andy测试模板001.xlsx"; filePathMap.put(paramName, filePath); //headers Map<String, Object> headers = new HashMap<>(); //COOKIE: Name=Value;Name2=Value2 headers.put("COOKIE", "token=OUFFNzQ0OUU5RDc1ODM0Q0M3QUM5NzdENThEN0Q1NkVEMjhGNzJGNEVGRTNCN0JEODM5NzAyNkI0OEE0MDcxNUZCMjdGNUMxMzdGRUE4MTcwRjVDNkJBRTE2ODgzQURDRjNCQjdBMTdCODc0MzA4QzFFRjlBQkM1MTA0N0MzMUU="); HttpResponse response = postFormData(url, filePathMap, keyValues, headers); System.out.println(response); } /** * 发送文本内容 * * @param urlStr * @param filePath * @return * @throws IOException */ public static HttpResponse postText(String urlStr, String filePath) throws IOException { HttpResponse response; URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "text/plain"); conn.setDoOutput(true); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream())); BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) { String line; while ((line = fileReader.readLine()) != null) { writer.write(line); } } catch (Exception e) { LOGGER.error("HttpUtils.postText 请求异常!", e); response = new HttpResponse(500, e.getMessage()); return response; } return getHttpResponse(conn); } } package awesome.data.structure.http; /** * @author: Andy * @time: 2019/7/10 14:41 * @since */ public class HttpResponse { private int code; private String content; public HttpResponse(int status, String content) { this.code = status; this.content = content; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String toString(){ return new StringBuilder("[ code = ").append(code) .append(" , content = ").append(content).append(" ]").toString(); } }

参考博客

  • https://www.cnblogs.com/tylerdonet/p/5722858.html
  • https://blog.csdn.net/a785975139/article/details/78781388

你可能感兴趣的:(http)