当前位置: 代码网 > it编程>编程语言>Java > Java httpclient请求form-data格式并设置boundary代码实现方法

Java httpclient请求form-data格式并设置boundary代码实现方法

2025年01月23日 Java 我要评论
在 java 开发中,经常会遇到需要使用 httpclient 发送 form-data 格式请求的场景。本文将详细介绍如何正确地实现这一操作,包括数据格式示例、常见报错及解决方法,以及完整的 jav

在 java 开发中,经常会遇到需要使用 httpclient 发送 form-data 格式请求的场景。本文将详细介绍如何正确地实现这一操作,包括数据格式示例、常见报错及解决方法,以及完整的 java 代码实现。

form-data 数据请求格式样例

我们先看下 form-data 数据的格式是长什么样的。
例如要传输 form-data 的键值对是:
a: aaa
b: bbb
请求的boundary设置如下:
addheader(“content-type”, “multipart/form-data;boundary=----12345”)

实际请求格式会加上boundary,请求示例如下

----12345
content-disposition: form-data; name="a"
aaa
----12345
content-disposition: form-data; name="b"
bbb

postman自动生成的 boundary 如下:

accept-encoding: gzip, deflate, br
connection: keep-alive
content-type: multipart/form-data; boundary=--------------------------477613155954799910398847

报错信息: missingservletrequestparameterexception解决方法

org.springframework.web.bind.missingservletrequestparameterexception

请求headers中的content-type类型不对
addheader(“content-type”, “application/json; charset=utf-8”);
json换成multipart/form-data
addheader(“content-type”, “multipart/form-data; charset=utf-8; boundary=” + new uuidgenerator().next());

报错信息: no multipart boundary was found 解决方法

org.apache.tomcat.util.http.fileupload.fileuploadexception: the request was rejected because no multipart boundary was found

这个报错是没有设置边界分隔符
解决方法:

headers中添加boundary

addheader("content-type", "multipart/form-data;boundary=" + boundary)

multipart/form-data 请求参数添加boundary

multipartentitybuilder multipartentitybuilder = multipartentitybuilder.create()
        .setcharset(standardcharsets.utf_8)
        // [重要]:设置 setboundary 边界分隔符
        .setboundary(boundary);

java代码实现

【错误】使用 urlencodedformentity 、basicnamevaluepair 请求失败(error)

public static jsonobject test(string url) throws ioexception {
    requestconfig requestconfig = requestconfig.custom().build();
    try (closeablehttpclient httpclient = httpclientbuilder.create().build()) {
        httppost post = new httppost(url);
        list<namevaluepair> list = new arraylist<>();
        basicnamevaluepair pair1 = new basicnamevaluepair("a", "aaa");
        basicnamevaluepair pair2 = new basicnamevaluepair("b", "bbb");
        list.add(pair1);
        list.add(pair2);
        urlencodedformentity urlencodedformentity = new urlencodedformentity(list,"utf-8");
        post.setentity(urlencodedformentity);
        string boundary = new uuidgenerator().next();
        // 设置请求格式 multipart/form-data
        post.addheader("content-type", "multipart/form-data;boundary=" + boundary);
        post.addheader("accept", "*/*");
        // utf-8 解决中文乱码
        post.addheader("accept-encoding", "utf-8");
        post.addheader("user-agent", " mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/123.0.0.0 safari/537.36");
        // 发送 post 请求
        httpresponse response = httpclient.execute(post);
        ...省略代码
}

上面的代码使用了 urlencodedformentity,basicnamevaluepair 去设置请求格式 multipart/form-data,虽然在 content-type中设置了 boundary,请求还是报请求参数错误:missingservletrequestparameterexception
是因为并没有在 multipart/form-data 的请求数据前后设置 分割边界符

【正确】使用 multipartentitybuilder 构造 boundary

要使用multipartentitybuilder,先引入maven

<dependency>
    <groupid>org.apache.httpcomponents</groupid>
    <artifactid>httpclient</artifactid>
    <version>4.5</version>
</dependency>
<dependency>
    <groupid>org.apache.httpcomponents</groupid>
    <artifactid>httpmime</artifactid>
    <version>4.5</version>
</dependency>

java用httpclient(apache)完整的纯文本form-data请求实现如下:

public enum test {
    ;
    private static final logger logger = loggerfactory.getlogger(test.class);
    /**
     * setconnecttimeout: 从客户端到url建立连接的超时时间
     */
    private static final int connect_timeout = 30 * 1000;
    /**
     * setsockettimeout: 连接上一个url后,获取response的返回等待时间
     */
    private static final int socket_timeout = 3600 * 1000;
    public static jsonobject posthttpformdatapair(string url, jsonobject requestbodyjson, map<string, string> headersmap, string... saverespheadername) {
        requestconfig requestconfig = requestconfig.custom()
                .setconnecttimeout(connect_timeout)
                .setsockettimeout(socket_timeout)
                .setcookiespec(cookiespecs.default)
                .build();
        cookiestore cookiestore = new basiccookiestore();
        // 默认是 closeablehttpclient httpclient = httpclientbuilder.create().build();
        try (closeablehttpclient httpclient = createsslclientdefaultbuilder()
                .setdefaultrequestconfig(requestconfig)
                .setdefaultcookiestore(cookiestore)
                .build()) {
            httppost post = new httppost(url);
            // [重要]:生成边界分隔符 boundary
            string boundary = new uuidgenerator().next();
            // [重要]:设置请求格式 multipart/form-data
            post.addheader("content-type", "multipart/form-data; charset=utf-8; boundary=" + boundary);
            post.addheader("accept", "*/*");
            post.addheader("accept-encoding", "utf-8");
            post.addheader("user-agent", " mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/123.0.0.0 safari/537.36");
            if (!collectionutils.isempty(headersmap)) {
                for (map.entry<string, string> entry : headersmap.entryset()) {
                    post.addheader(entry.getkey(), entry.getvalue());
                }
            }
            // 构造 formdata 请求数据
            multipartentitybuilder multipartentitybuilder = multipartentitybuilder.create()
                    .setcharset(standardcharsets.utf_8)
                    // [重要]:设置 setboundary 边界分隔符
                    .setboundary(boundary);
            multipartentitybuilder.addtextbody("a", "aaa");
            multipartentitybuilder.addtextbody("b", "bbb");
            httpentity postformdatabody = multipartentitybuilder.build();
            // 请求参数
            post.setentity(postformdatabody);
            // 发送 post 请求
            httpresponse response = httpclient.execute(post);
            if (response == null) {
                throw new runtimeexception("response is null");
            } else if (response.getstatusline().getstatuscode() == httpstatus.sc_ok) {
                return getresponsejsonobject(response, saverespheadername);
            } else {
                logger.warn("response status is not 200");
                return getresponsejsonobject(response, saverespheadername);
            }
        } catch (exception ex) {
            logger.error("error:", ex);
            throw new runtimeexception("系统异常");
        }
    }
    @notnull
    private static jsonobject getresponsejsonobject(httpresponse response, string[] saverespheadername) throws ioexception {
        inputstream in = response.getentity().getcontent();
        bufferedreader reader = new bufferedreader(new inputstreamreader(in));
        string lines;
        stringbuilder responsemsg = new stringbuilder("");
        while ((lines = reader.readline()) != null) {
            lines = new string(lines.getbytes(), standardcharsets.utf_8);
            responsemsg.append(lines);
        }
        reader.close();
        in.close();
        jsonobject jsonobject = new jsonobject();
        jsonobject.put("message", responsemsg.tostring());
        // save header
        for (string name : saverespheadername) {
            jsonobject.put(name, response.getheaders(name));
        }
        return jsonobject;
    }
    /**
     * 绕过https证书校验
     */
    public static httpclientbuilder createsslclientdefaultbuilder() {
        httpclientbuilder httpclientbuilder = null;
        try {
            sslcontextbuilder builder = new sslcontextbuilder();
            // 实现该接口,证书受信任的x509证书校验为true
            builder.loadtrustmaterial(null, (chain, authtype) -> true);
            // 创建httpsurlconnection对象,并设置其sslsocketfactory对象
            sslconnectionsocketfactory socketfactory = new sslconnectionsocketfactory(builder.build(), new string[]{"tlsv1.2"}, null, noophostnameverifier.instance);
            //  httpsurlconnection对象就可以正常连接https了,无论其证书是否经权威机构的验证,只要实现了接口x509trustmanager的类myx509trustmanager信任该证书。
            httpclientbuilder = httpclients.custom().setsslsocketfactory(socketfactory);
        } catch (exception e) {
            e.printstacktrace();
            throw new runtimeexception("系统异常");
        }
        return httpclientbuilder;
    }
}

总结

想要代码实现 form-data格式的请求要注意下面2点:

设置 boundary 边界分隔符

设置 content-type

到此这篇关于java httpclient请求form-data格式并设置boundary代码实现方法的文章就介绍到这了,更多相关java httpclient请求form-data格式内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com