zoukankan      html  css  js  c++  java
  • httpclient通过post multipart/form-data 上传文件


    1. https://blog.csdn.net/liqing0013/article/details/95514125

    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 = " ";

    /**
    * post 请求:以表单方式提交数据
    * <p>
    * 由于 multipart/form-data 不是 http 标准内容,而是属于扩展类型,
    * 因此需要自己构造数据结构,具体如下:
    * <p>
    * 1、首先,设置 Content-Type
    * <p>
    * Content-Type: multipart/form-data; boundary=${bound}
    * <p>
    * 其中${bound} 是一个占位符,代表我们规定的分割符,可以自己任意规定,
    * 但为了避免和正常文本重复了,尽量要使用复杂一点的内容
    * <p>
    * 2、设置主体内容
    * <p>
    * --${bound}
    * Content-Disposition: form-data; name="userName"
    * <p>
    * Andy
    * --${bound}
    * Content-Disposition: form-data; name="file"; filename="测试.excel"
    * Content-Type: application/octet-stream
    * <p>
    * 文件内容
    * --${bound}--
    * <p>
    * 其中${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();
    }
    }


    2. https://bbs.huaweicloud.com/blogs/109206

    public static String httpClientUploadFile(String url, File file) {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    String result = "";
    //每个post参数之间的分隔。随意设定,只要不会和其他的字符串重复即可。
    String boundary ="--------------4585696313564699";
    try {
    //文件名
    String fileName = file.getName();
    HttpPost httpPost = new HttpPost(url);
    //设置请求头
    httpPost.setHeader("Content-Type","multipart/form-data; boundary="+boundary);

    //HttpEntity builder
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    //字符编码
    builder.setCharset(Charset.forName("UTF-8"));
    //模拟浏览器
    builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    //boundary
    builder.setBoundary(boundary);
    //multipart/form-data
    builder.addPart("multipartFile",new FileBody(file));
    // binary
    // builder.addBinaryBody("name="multipartFile"; filename="test.docx"", new FileInputStream(file), ContentType.MULTIPART_FORM_DATA, fileName);// 文件流
    //其他参数
    builder.addTextBody("filename", fileName, ContentType.create("text/plain", Consts.UTF_8));
    //HttpEntity
    HttpEntity entity = builder.build();
    httpPost.setEntity(entity);
    // 执行提交
    HttpResponse response = httpClient.execute(httpPost);
    //响应
    HttpEntity responseEntity = response.getEntity();
    if (responseEntity != null) {
    // 将响应内容转换为字符串
    result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
    }
    } catch (IOException e) {
    e.printStackTrace();
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    try {
    httpClient.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    System.err.println("result"+result);
    return result;
    }

    //main 方法
    public static void main(String[] args) {
    httpClientUploadFile("http://127.0.0.1:8080/upload",new File("d:/test/test.docx"));
    }


    3. https://blog.csdn.net/qq_33745005/article/details/108536630
    /**
    *@param url 请求地址
    *@param json提交参数
    *@param code 编码
    *@param file 文件对象
    */
    public String postFormdata(String url, JSONObject json, String code, File file) {
    String res = null;
    CloseableHttpResponse response = null;
    try {
    HttpPost httpPost = new HttpPost(url);
    String boundary ="--------------4585696313564699";
    httpPost.setHeader("Content-Type","multipart/form-data; boundary="+boundary);

    //创建 MultipartEntityBuilder,以此来构建我们的参数
    MultipartEntityBuilder EntityBuilder = MultipartEntityBuilder.create();
    //设置字符编码,防止乱码
    ContentType contentType=ContentType.create("text/plain",Charset.forName(code));
    //遍历json参数
    for(String str:json.keySet()){
    EntityBuilder.addPart(str, new StringBody(json.get(str).toString(),contentType));
    }
    EntityBuilder.addPart("file",new FileBody(file));
    //模拟浏览器
    EntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    //boundary
    EntityBuilder.setBoundary(boundary);

    httpPost.setEntity(EntityBuilder.build());

    response = httpclient.execute(httpPost);
    HttpEntity entity2 = response.getEntity();
    res = EntityUtils.toString(entity2, code);
    logger.info(res);
    EntityUtils.consume(entity2);
    } catch (Exception e) {
    logger.error(url, e);
    } finally {
    if (response != null) {
    try {
    response.close();
    } catch (IOException e) {
    }
    }
    }
    return res;
    }

  • 相关阅读:
    如何上传整个项目或者是文件夹到github
    阅读笔记16-架构师推荐:提高90%开发效率的工具推荐
    阅读笔记15-这些普通的程序猿,如今都已进阶成为技术大佬
    python爬虫——爬取淘票票正在热映电影
    阅读笔记12-Java 面试题 —— 老田的蚂蚁金服面试经历
    SOA架构设计案例分析
    阅读笔记11-孤独后厂村:30万互联网人跳不出的中国硅谷
    阅读笔记09-Java程序员必备的Intellij插件
    阅读笔记08-程序员依然是这个时代,贫寒学子翻身的不二选择
    os.path.join()
  • 原文地址:https://www.cnblogs.com/kelelipeng/p/14543071.html
Copyright © 2011-2022 走看看